comp.lang.ada
 help / color / mirror / Atom feed
Search results ordered by [date|relevance]  view[summary|nested|Atom feed]
thread overview below | download mbox.gz: |
* Re: GNAT Community 2020 (20200818-93): Big_Integer
  2023-06-30 19:28  3% GNAT Community 2020 (20200818-93): Big_Integer Frank Jørgen Jørgensen
@ 2023-06-30 21:07  2% ` Dmitry A. Kazakov
  0 siblings, 0 replies; 200+ results
From: Dmitry A. Kazakov @ 2023-06-30 21:07 UTC (permalink / raw)


On 2023-06-30 21:28, Frank Jørgen Jørgensen wrote:

> I'm running the below program with GNAT Community 2020 (20200818-93)
> on Windows 11 Home.
> I have some problems trying to save big numbers to a file - so I noticed this behaviour:
> If I open Test.dat in Visual Studio Hex editor,  it seems like this program saves this big number with a different bit pattern each time.
> Is that as expected?
> I do have some problems reading back the big numbers in my real code.
> When I compile I get the warning: "Ada.Numerics.Big_Numbers.Big_Integers"  is an Ada 202x unit.
> 
> --
> with Ada.Streams.Stream_IO; use Ada.Streams.Stream_IO;
> with Ada.Numerics.Big_Numbers.Big_Integers;
> 
> procedure Test is
> 
>        B1 : Ada.Numerics.Big_Numbers.Big_Integers.Big_Integer;
>        F1 : File_Type;
>        S1 : Stream_Access;
>     begin
>        B1 := 1;
> 
>        Ada.Streams.Stream_IO.Create (F1, Out_File, "Test.dat");
>        S1 := Ada.Streams.Stream_IO.Stream (F1);
>        Ada.Numerics.Big_Numbers.Big_Integers.Big_Integer'Write(S1, B1);
>        Ada.Numerics.Big_Numbers.Big_Integers.Big_Integer'Output(S1, B1);
>        Ada.Streams.Stream_IO.Close (F1);
> end Test;

As a general rule, you should never use predefined implementations of 
stream attributes except for Stream_Element or Character. Anything else 
you must always override or else not use.

If you want to serialize signed integers use some portable format for 
it. E.g. a chained encoding.

Here is a test program for a straightforward implementation of chained 
store/restore:
-------------------------
with Ada.Streams.Stream_IO; use Ada.Streams.Stream_IO;
with Ada.Numerics.Big_Numbers.Big_Integers;
with Ada.Exceptions;
with Ada.IO_Exceptions;

procedure Test is

    use Ada.Streams;
    use Ada.Numerics.Big_Numbers.Big_Integers;
    use Ada.Exceptions;
    use Ada.Streams.Stream_IO;

    Two : constant Big_Integer := To_Big_Integer (2);

    package Conversions is new Unsigned_Conversions (Stream_Element);
    use Conversions;

    function Get
             (  Stream : in out Root_Stream_Type'Class
             )  return Big_Integer is
       Result   : Big_Integer;
       Power    : Natural := 6;
       Negative : Boolean;
       Buffer   : Stream_Element_Array (1..1);
       Last     : Stream_Element_Offset;
       This     : Stream_Element renames Buffer (1);
    begin
       Stream.Read (Buffer, Last);
       if Last /= 1 then
          raise End_Error;
       end if;
       Result   := To_Big_Integer ((This and 2#0111_1110#) / 2);
       Negative := 0 /= (This and 1);
       if 0 = (This and 16#80#) then
          if Negative then
             return -Result - 1;
          else
             return Result;
          end if;
       end if;
       loop
          Stream.Read (Buffer, Last);
          if Last /= 1 then
             raise End_Error;
          end if;
          Result := Result +
             Two**Power * To_Big_Integer (This and 16#7F#);
          if 0 = (This and 16#80#) then
             if Negative then
                return -Result - 1;
             else
                return Result;
             end if;
          end if;
          Power := Power + 7;
       end loop;
    end Get;

    procedure Put
              (  Stream : in out Root_Stream_Type'Class;
                 Value  : Big_Integer
              )  is
       Item   : Big_Integer := Value;
       Buffer : Stream_Element_Array (1..1);
       This   : Stream_Element renames Buffer (1);
    begin
       if Item >= 0 then
          Item := Value;
          This := From_Big_Integer (Item mod (16#40#)) * 2;
       else
          Item := -(Value + 1);
          This := From_Big_Integer (Item mod (16#40#)) * 2 + 1;
       end if;
       Item := Item / 16#40#;
       if Item = 0 then
          Stream.Write (Buffer);
          return;
       end if;
       This := This or 16#80#;
       Stream.Write (Buffer);
       loop
          This := From_Big_Integer (Item mod 16#80#) or 16#80#;
          Item := Item / 16#80#;
          if Item = 0 then
             This := This and 16#7F#;
             Stream.Write (Buffer);
             return;
          end if;
          Stream.Write (Buffer);
       end loop;
    end Put;

    F : File_Type;
begin
    Create (F, Out_File, "Test.dat");
    for I in -1_000_000..1_000_000 loop
       Put (Stream (F).all, To_Big_Integer (I));
    end loop;
    Close (F);
    Open (F, In_File, "Test.dat");
    for I in -1_000_000..1_000_000 loop
       declare
          Value : constant Big_Integer := Get (Stream (F).all);
       begin
          if Value /= To_Big_Integer (I) then
             raise Data_Error;
          end if;
       end;
    end loop;
    Close (F);
end Test;
-------------------------
The above could be optimized to work with buffers rather than 
reading/writing stream octets one by one. It is a long story, but 
normally you would implement some data blocks with the length count on 
top of the stream in order to avoid inefficient octet by octet reading 
and add an error correction layer.

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

^ permalink raw reply	[relevance 2%]

* GNAT Community 2020 (20200818-93):   Big_Integer
@ 2023-06-30 19:28  3% Frank Jørgen Jørgensen
  2023-06-30 21:07  2% ` Dmitry A. Kazakov
  0 siblings, 1 reply; 200+ results
From: Frank Jørgen Jørgensen @ 2023-06-30 19:28 UTC (permalink / raw)


Hi

I'm running the below program with GNAT Community 2020 (20200818-93)
on Windows 11 Home.
I have some problems trying to save big numbers to a file - so I noticed this behaviour:
If I open Test.dat in Visual Studio Hex editor,  it seems like this program saves this big number with a different bit pattern each time.
Is that as expected?
I do have some problems reading back the big numbers in my real code.
When I compile I get the warning: "Ada.Numerics.Big_Numbers.Big_Integers"  is an Ada 202x unit.

Frank

--
with Ada.Streams.Stream_IO; use Ada.Streams.Stream_IO;
with Ada.Numerics.Big_Numbers.Big_Integers;

procedure Test is

      B1 : Ada.Numerics.Big_Numbers.Big_Integers.Big_Integer;
      F1 : File_Type;
      S1 : Stream_Access;
   begin
      B1 := 1;

      Ada.Streams.Stream_IO.Create (F1, Out_File, "Test.dat");
      S1 := Ada.Streams.Stream_IO.Stream (F1);
      Ada.Numerics.Big_Numbers.Big_Integers.Big_Integer'Write(S1, B1);
      Ada.Numerics.Big_Numbers.Big_Integers.Big_Integer'Output(S1, B1);
      Ada.Streams.Stream_IO.Close (F1);
end Test;

^ permalink raw reply	[relevance 3%]

* Re: Usage of Stream Set_Index() function
  2022-01-14 20:35  0% ` Niklas Holsti
@ 2022-01-15 10:36  0%   ` DrPi
  0 siblings, 0 replies; 200+ results
From: DrPi @ 2022-01-15 10:36 UTC (permalink / raw)


Le 14/01/2022 à 21:35, Niklas Holsti a écrit :
> On 2022-01-14 20:30, DrPi wrote:
>>
>> Hi,
>>
>> I'm writing an application where I read a file with a complex structure.
>> For this, I use Ada.Streams.Stream_IO package.
>> To read the file, I need to position the file pointer to the correct 
>> location. I do this using Set_Index().
>>
>> In ARM A.12.1, it is stated :
>> For Read and Write with a Positive_Count parameter, the value of the 
>> current index is set to the value of the Positive_Count parameter plus 
>> the number of stream elements read or written.
>>
>> I don't understand the "plus the number of stream elements read or 
>> written".
> 
> 
> For Write, the ARM also says: "The Write procedure with a Positive_Count 
> parameter starts writing at the specified index". And then, after the 
> data have been written, naturally the current index of the stream has 
> been increased, to point at the position after the written data. That is 
> the meaning of the "plus" phrase.
> 
> And Read analogously. The "plus" phrase explains what the value of the 
> current index is _after_ the Read or Write. But both the Read and the 
> Write _start_ reading/writing at the index given in the From/To parameters.
> 
> 
>> Does this mean one can't go back to beginning of file once data have 
>> been read ?
> 
> 
> No, Set_Index can do that, whether the last action was writing or 
> reading. And the Write/Read with an index parameter can also do that.
> 
> But if you have set the current index to the desired position with 
> Set_Index, you don't need to use the Read/Write that have a 
> Positive_Count (index) parameter.
> 
> This code:
> 
>     Set_Index (F, I);
>     Write (F, Item);
> 
> is equivalent to:
> 
>     Write (F, Item, I);
> 
> and ditto Read.

Ok, so Set_Index() works as expected. Nothing special.

Reading the LRM made me understand things incorrectly because of the way 
it is written.

It is written :
32 The Set_Index procedure sets the current index to the specified value.

Then, it is written :
32.1/1 ...
32.2/1 ...
...

Reading this, I thought 32.1/1, 32.2/1 etc lines apply to 32 
(Set_Index() function).
So, I was completely lost to understand the meaning of these lines.

^ permalink raw reply	[relevance 0%]

* Re: Usage of Stream Set_Index() function
  2022-01-14 18:30  2% Usage of Stream Set_Index() function DrPi
@ 2022-01-14 20:35  0% ` Niklas Holsti
  2022-01-15 10:36  0%   ` DrPi
  0 siblings, 1 reply; 200+ results
From: Niklas Holsti @ 2022-01-14 20:35 UTC (permalink / raw)


On 2022-01-14 20:30, DrPi wrote:
> 
> Hi,
> 
> I'm writing an application where I read a file with a complex structure.
> For this, I use Ada.Streams.Stream_IO package.
> To read the file, I need to position the file pointer to the correct 
> location. I do this using Set_Index().
> 
> In ARM A.12.1, it is stated :
> For Read and Write with a Positive_Count parameter, the value of the 
> current index is set to the value of the Positive_Count parameter plus 
> the number of stream elements read or written.
> 
> I don't understand the "plus the number of stream elements read or 
> written".


For Write, the ARM also says: "The Write procedure with a Positive_Count 
parameter starts writing at the specified index". And then, after the 
data have been written, naturally the current index of the stream has 
been increased, to point at the position after the written data. That is 
the meaning of the "plus" phrase.

And Read analogously. The "plus" phrase explains what the value of the 
current index is _after_ the Read or Write. But both the Read and the 
Write _start_ reading/writing at the index given in the From/To parameters.


> Does this mean one can't go back to beginning of file once data have 
> been read ?


No, Set_Index can do that, whether the last action was writing or 
reading. And the Write/Read with an index parameter can also do that.

But if you have set the current index to the desired position with 
Set_Index, you don't need to use the Read/Write that have a 
Positive_Count (index) parameter.

This code:

    Set_Index (F, I);
    Write (F, Item);

is equivalent to:

    Write (F, Item, I);

and ditto Read.

^ permalink raw reply	[relevance 0%]

* Usage of Stream Set_Index() function
@ 2022-01-14 18:30  2% DrPi
  2022-01-14 20:35  0% ` Niklas Holsti
  0 siblings, 1 reply; 200+ results
From: DrPi @ 2022-01-14 18:30 UTC (permalink / raw)



Hi,

I'm writing an application where I read a file with a complex structure.
For this, I use Ada.Streams.Stream_IO package.
To read the file, I need to position the file pointer to the correct 
location. I do this using Set_Index().

In ARM A.12.1, it is stated :
For Read and Write with a Positive_Count parameter, the value of the 
current index is set to the value of the Positive_Count parameter plus 
the number of stream elements read or written.

I don't understand the "plus the number of stream elements read or written".

Does this mean one can't go back to beginning of file once data have 
been read ?

Nicolas

^ permalink raw reply	[relevance 2%]

* Re: Hi! How I can make _indexed_ stream file Input/Output ? Thanks.
  2021-07-05  4:06  0%   ` zac brown
@ 2021-07-05  4:06  0%     ` zac brown
  0 siblings, 0 replies; 200+ results
From: zac brown @ 2021-07-05  4:06 UTC (permalink / raw)


On Monday, July 5, 2021 at 2:06:36 PM UTC+10, zac brown wrote:
> On Saturday, July 3, 2021 at 6:57:31 AM UTC+10, Shark8 wrote: 
> > On Sunday, June 27, 2021 at 1:33:28 PM UTC-6, daniel wrote: 
> > > How I can make _indexed_ stream file Input/Output ? 
> > > 
> > > For 'indexed' i mean manually setting file position: 
> > > => 'from' in $type'input() and 
> > > => 'to' in $type'output() 
> > > 
> > > Actually I use Ada.Streams.Stream_IO. 
> > > 
> > > My main need is examples. 
> > > 
> > > Thanks! 
> > > Best Whishes, 
> > > Dani. 
> > Streams are a bit different than files; you see, streams are an abstraction on input/output and therefore different than files. Consider, for example, an output stream that controls a radio transmitter. There's no possible way to "unsend" the data: it's a write-only device. 
> > 
> > If you're using Ada's standard library, with the XXX_IO packages, I believe what you want is Ada.Direct_IO.

^ permalink raw reply	[relevance 0%]

* Re: Hi! How I can make _indexed_ stream file Input/Output ? Thanks.
  2021-07-02 20:57  0% ` Shark8
@ 2021-07-05  4:06  0%   ` zac brown
  2021-07-05  4:06  0%     ` zac brown
  0 siblings, 1 reply; 200+ results
From: zac brown @ 2021-07-05  4:06 UTC (permalink / raw)


On Saturday, July 3, 2021 at 6:57:31 AM UTC+10, Shark8 wrote:
> On Sunday, June 27, 2021 at 1:33:28 PM UTC-6, daniel wrote: 
> > How I can make _indexed_ stream file Input/Output ? 
> > 
> > For 'indexed' i mean manually setting file position: 
> > => 'from' in $type'input() and 
> > => 'to' in $type'output() 
> > 
> > Actually I use Ada.Streams.Stream_IO. 
> > 
> > My main need is examples. 
> > 
> > Thanks! 
> > Best Whishes, 
> > Dani.
> Streams are a bit different than files; you see, streams are an abstraction on input/output and therefore different than files. Consider, for example, an output stream that controls a radio transmitter. There's no possible way to "unsend" the data: it's a write-only device. 
> 
> If you're using Ada's standard library, with the XXX_IO packages, I believe what you want is Ada.Direct_IO.

^ permalink raw reply	[relevance 0%]

* Re: Hi! How I can make _indexed_ stream file Input/Output ? Thanks.
  2021-06-27 19:33  2% Hi! How I can make _indexed_ stream file Input/Output ? Thanks Daniel Norte Moraes
  2021-06-28  1:36  0% ` Dennis Lee Bieber
@ 2021-07-02 20:57  0% ` Shark8
  2021-07-05  4:06  0%   ` zac brown
  1 sibling, 1 reply; 200+ results
From: Shark8 @ 2021-07-02 20:57 UTC (permalink / raw)


On Sunday, June 27, 2021 at 1:33:28 PM UTC-6, daniel wrote:
> How I can make _indexed_ stream file Input/Output ? 
> 
> For 'indexed' i mean manually setting file position: 
> => 'from' in $type'input() and 
> => 'to' in $type'output() 
> 
> Actually I use Ada.Streams.Stream_IO. 
> 
> My main need is examples. 
> 
> Thanks! 
> Best Whishes, 
> Dani.

Streams are a bit different than files; you see, streams are an abstraction on input/output and therefore different than files. Consider, for example, an output stream that controls a radio transmitter. There's no possible way to "unsend" the data: it's a write-only device.

If you're using Ada's standard library, with the XXX_IO packages, I believe what you want is Ada.Direct_IO.

^ permalink raw reply	[relevance 0%]

* Re: Hi! How I can make _indexed_ stream file  Input/Output ? Thanks.
  2021-06-27 19:33  2% Hi! How I can make _indexed_ stream file Input/Output ? Thanks Daniel Norte Moraes
@ 2021-06-28  1:36  0% ` Dennis Lee Bieber
  2021-07-02 20:57  0% ` Shark8
  1 sibling, 0 replies; 200+ results
From: Dennis Lee Bieber @ 2021-06-28  1:36 UTC (permalink / raw)


On Sun, 27 Jun 2021 12:33:27 -0700 (PDT), Daniel Norte Moraes
<danielcheagle@gmail.com> declaimed the following:

>How I can make _indexed_  stream file  Input/Output ?
>
>For 'indexed' i mean manually  setting file position:
> => 'from'  in $type'input() and
>=> 'to' in $type'output()
>
>Actually I use Ada.Streams.Stream_IO.
>
>My main need is examples.
>

	What part of
https://www.adaic.org/resources/add_content/standards/05aarm/html/AA-A-12-1.html
is lacking?

"""
21	    -- Operations on position within file
22	    procedure Set_Index(File : in File_Type; To : in Positive_Count);
23	    function Index(File : in File_Type) return Positive_Count;
	    function Size (File : in File_Type) return Count;
"""
"""
31/1	{8652/0055} {AI95-00026-01} The Index function returns the current
file index, as a count (in stream elements) from the beginning of the file.
The position of the first element in the file is 1. 
31.a/1	This paragraph was deleted.Ramification: The notion of Index for
Stream_IO is analogous to that of Index in Direct_IO, except that the
former is measured in Stream_Element units, whereas the latter is in terms
of Element_Type values. 
32		The Set_Index procedure sets the current index to the specified
value.
32.1/1	   {8652/0055} {AI95-00026-01} If positioning is supported for the
external file, the current index is maintained as follows:
32.2/1	   {8652/0055} {AI95-00026-01} For Open and Create, if the Mode
parameter is Append_File, the current index is set to the current size of
the file plus one; otherwise, the current index is set to one.
32.3/1	 {8652/0055} {AI95-00026-01} For Reset, if the Mode parameter is
Append_File, or no Mode parameter is given and the current mode is
Append_File, the current index is set to the current size of the file plus
one; otherwise, the current index is set to one.
"""
"""
33		If positioning is not supported for the given file, then a call of
Index or Set_Index propagates Use_Error. Similarly, a call of Read or Write
with a Positive_Count parameter propagates Use_Error.
33.a/2	Implementation Note: {AI95-00085-01} It is permissible for an
implementation to implement mode Append_File using the Unix append mode
(the O_APPEND bit). Such an implementation does not support positioning
when the mode is Append_File, and therefore the operations listed above
must raise Use_Error. This is acceptable as there is no requirement that
any particular file support positioning; therefore it is acceptable that a
file support positioning when opened with mode Out_File, and the same file
not support positioning when opened with mode Append_File. But it is not
acceptable for a file to support positioning (by allowing the above
operations), but to do something other than the defined semantics (that is,
always write at the end, even when explicitly commanded to write somewhere
else). 
"""


-- 
	Wulfraed                 Dennis Lee Bieber         AF6VN
	wlfraed@ix.netcom.com    http://wlfraed.microdiversity.freeddns.org/

^ permalink raw reply	[relevance 0%]

* Hi! How I can make _indexed_ stream file  Input/Output ? Thanks.
@ 2021-06-27 19:33  2% Daniel Norte Moraes
  2021-06-28  1:36  0% ` Dennis Lee Bieber
  2021-07-02 20:57  0% ` Shark8
  0 siblings, 2 replies; 200+ results
From: Daniel Norte Moraes @ 2021-06-27 19:33 UTC (permalink / raw)


How I can make _indexed_  stream file  Input/Output ?

For 'indexed' i mean manually  setting file position:
 => 'from'  in $type'input() and
=> 'to' in $type'output()

Actually I use Ada.Streams.Stream_IO.

My main need is examples.

Thanks!
Best Whishes,
Dani.

^ permalink raw reply	[relevance 2%]

* Re: surprise data from Ada.Sequential_IO
  @ 2021-03-22 17:48  2% ` Dmitry A. Kazakov
  0 siblings, 0 replies; 200+ results
From: Dmitry A. Kazakov @ 2021-03-22 17:48 UTC (permalink / raw)


On 2021-03-22 18:13, John Perry wrote:

> I was using gnat 2020 CE on a Linux machine the other day, and wanted to write out data for three different types T1, T2, T3 to a file. I instantiated a Sequential_IO package for each; call them P1, P2, P3.
> 
> The following worked as expected (sorry for the abbreviations but I think it will be clear):
> 
>>> P1.Create; P1.Write; P1.Close; P2.Open(Append_File); P2.Write; P2.Close;
> 
> However, this:
> 
>>> P3.Open(Append_File); P3.Write; P3.Close;
> 
> ...wrote a few bytes of junk between T2's data and T3's data.
> 
> I used a hex editor to check the output file between writes, and there was no junk after P2.Close nor after P3.Open; it always came at the beginning of P3.Write.
> 
> I reworked the type definitions so that T3's data was included at the end of T2, and in this case P2.Write wrote the data properly, as desired. However, this is not the sort of permanent solution I'd want.
> 
> Has anyone else encountered this? Could this be due to alignment issues? Is there some way to avoid this without putting the data there?

I did not use Sequential_IO for decades. I doubt it was ever intended 
for the misuse you invented.

For practical point of view, I would consider this package obsolete, 
superseded by Ada.Streams.Stream_IO. It is exactly meant for your case, 
especially if you override the attributes of T1, T2, T3 (to make it 
portable).

And you are in full control of what is going on, e.g. no stuff like 
vertical formats and stupid EOF sequences.

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

^ permalink raw reply	[relevance 2%]

* Re: General circular buffer example not tied to any specific type
  @ 2020-09-24  4:39  2%   ` J-P. Rosen
  0 siblings, 0 replies; 200+ results
From: J-P. Rosen @ 2020-09-24  4:39 UTC (permalink / raw)


Le 24/09/2020 à 06:10, nimaopatel121@gmail.com a écrit :
> On Saturday, 4 July 2020 22:30:28 UTC+5:30, Daniel  wrote:
>> Hello, any theoric 
>>  example of buffer i can find is always tied to an specific type.
>>
>> I'm looking for any example of ravenscar buffer able for using any type of data at the same time.
>>
>> I suppose it will need to serialize all  data and manipulate it as a group of bytes.
>>
>> Does any body knows any example of this written in Ada?
> 
Hmmm, you know, Ada is a strongly typed language, therefore what you put
in a buffer must have a well defined type.

There are two possibilities:
1) If you can accept several buffers, one for each type, make it generic
and instantiate it as many times as you need

2) Make a buffer of Stream_Elements, and use the streaming attributes
('Read, 'Write) to turn any type into stream elements.

Ada.Streams.Stream_IO can also be handy in some cases.

-- 
J-P. Rosen
Adalog
2 rue du Docteur Lombard, 92441 Issy-les-Moulineaux CEDEX
Tel: +33 1 45 29 21 52, Fax: +33 1 45 29 25 00
http://www.adalog.fr

^ permalink raw reply	[relevance 2%]

* article on acces types and dynamic serialization in Ada (2003)
@ 2018-02-21 23:57  2% Mehdi Saada
  0 siblings, 0 replies; 200+ results
From: Mehdi Saada @ 2018-02-21 23:57 UTC (permalink / raw)


Hello everyone.
I already mailed you Simon Wright about it, but I've more info and questions, so it put it here. First the context:
I played with streams yesterday to learn more, and stumbled on something not really intuitive, at least. what means exactly Some_access_type'Write(Stream1, Some_Pointer) ?
I could figure out it's implementation defined, so you can't guess.
So that
Some_access_type'Write(stream(Stream_File), Pointer1);
...
Reset(Stream_File, IN_FILE);
Some_access_type'Read(stream(Stream_file), Pointer2);
doesn't work: reaching Pointer2.all raises "erroneous memory access", though Pointer2 isn't null.
Strange, since in my exemple, all happen in the same, hum, "scope of declaration" (apropriate term ?). Any address or whatever information the pointer is made of, should still be valid. Any pool pointed at still exists.
Doesn't feel like a "sane" legal behavior. I also saw a "normal" record object with a pool-specific pointer like this one
type FOO is record
  ...
  BAR: access INTEGER := new INTEGER'(15);
end record;
serializes well, I can read Bar.all. Funny, but where the difference since (according to Ada wikibook) a priori the default 'Write is called for each record component ?

Then I found today that https://infoscience.epfl.ch/record/54724/files/IC_TECH_REPORT_200363.pdf : Automatic Serialization of Dynamic Structures in Ada Technical Report

I was surprised I could read and understand it all with some concentration. And a bit proud, to be honnest ! I would have thought it to be like Chinese at my level.
It was 13 years ago, but I couldn't find a more recent papier on the subject of dynamic serialization, nor has new Dynamic_Stream aspects/attributes been added since then. I didn't read anything either in the stream or access types related sections.

I tried more, but can't write well yet that more complicated exemple:
with Ada.Streams.Stream_IO, Ada.Strings.Unbounded.Text_IO, Ada.Text_IO;
use Ada.Streams.Stream_IO, Ada.Streams, Ada.Strings.Unbounded, Ada.Strings.Unbounded.Text_IO;
procedure Main is
   subtype TSF is File_Type;
   FILE : TSF;
   type CHAMPS;
   type ACCESS_CHAMPS is access ALL CHAMPS;
   type CHAMPS (A: ACCESS_CHAMPS) is record
      NOTE : NATURAL range 0 .. 20 := 0;
   end record;
   
   C2, C1 , C3  :  aliased CHAMPS := (A => null, note => 5); 
begin
        
   C1 := (C2'Access, 14);
   C2 := (A => C1'Access, Note => 5 ); 
   Create (FILE, Append_File, Name => "tentative.stream");
   CHAMPS'Write (Stream (FILE), C2);
   Reset (File => FILE,
	  Mode => In_File );
   CHAMPS'Read(Stream(FILE), C3);
   ada.Text_IO.Put_line (INTEGER'Image (C3.A.all.Note));
   CLOSE(FILE);
end;

raises CONSTRAINT_ERROR : main.adb:15 discriminant check failed
I read as I could about access discrimant aliasing and autoreferencing types, but visibly lack practice ;-)  
Could you help me finish that exemple ? I would be delighted to see what happens by myself, since the former exemple (Some_Access'Write and 'Read) proves interesting.

Gosh, the pleasure these things give me...

^ permalink raw reply	[relevance 2%]

* Re: Finding the end of a stream from a socket
  2017-10-21 17:34  0%   ` Andrew Shvets
@ 2017-10-21 19:18  0%     ` Andrew Shvets
  0 siblings, 0 replies; 200+ results
From: Andrew Shvets @ 2017-10-21 19:18 UTC (permalink / raw)


On Saturday, October 21, 2017 at 1:34:15 PM UTC-4, Andrew Shvets wrote:
> On Saturday, October 21, 2017 at 4:44:42 AM UTC-4, Dmitry A. Kazakov wrote:
> > On 2017-10-21 04:05, Andrew Shvets wrote:
> > 
> > > I've been recently trying to make a small TCP server (a toy.) I have
> > > a channel that reads Characters and was trying to find the end of
> > > the stream. Reading the documentation, I came across the following
> > > in  g-socket.ads:
> > > 
> > > type Stream_Access is access all Ada.Streams.Root_Stream_Type'Class;
> > > --  Same interface as Ada.Streams.Stream_IO
> > > 
> > > I was trying to have a way to find out when the last Character was 
> > > read from the stream. I could catch the Ada.IO_Exceptions.End_Error 
> > > exception, but I'm wondering if there is a better way.
> > 
> > End_Error is the best possible way, when applied. GNAT socket streams do 
> > not raise End_Error, AFAIK.
> > 
> > > while not Ada.Streams.Stream_IO.End_Of_File(Channel) loop
> > >    Character'Read(Channel, Received_Char);
> > >    Ada.Text_IO.Put(Received_Char);
> > > end loop;
> > 
> > This is a bad idea even when if it can work. In the case of sockets 
> > there is no file end. When the connection is closed by the peer the 
> > stream will stop both returning data and blocking. I suppose that will 
> > cause Constraint_Error in Character'Read.
> > 
> > In practice there is a higher level protocol on top of the socket 
> > stream, so that it is always known how many octets to read next.
> > 
> > Regarding your case, try this:
> > 
> >     Buffer : Stream_Element_Array (1..Buffer_Size);
> >     Last   : Stream_Element_Offset;
> > begin
> >     loop
> >        Receive_Socket (Socket, Buffer, Last);
> >        exit when Last < Buffer'First; -- Connection is closed by the peer
> >        for Octet in Buffer'First..Last loop -- Dump octets as-is
> >           Put (Character'Val (Buffer (Octet)));
> >        end loop;
> >     end loop;
> > 
> > -- 
> > Regards,
> > Dmitry A. Kazakov
> > http://www.dmitry-kazakov.de
> 
> Hi Dmitry,
> 
> This is my entire code.
> https://gist.github.com/anonymous/b7c3a5bdcd8c78453a643b6785573131

On this line:
GNAT.Sockets.Connect_Socket(Receiver,  Client_Addr);


I get the following exception:
!! TCP Server started !!
FOO 1

raised GNAT.SOCKETS.SOCKET_ERROR :[10022] Unknown system error


Weird, I thought, then I uncommented the Connect_Socket procedure call, since the socket is already being used to listen, it should be "connected".  When I did this, I got this error:

https://gist.github.com/anonymous/b79594f71309df87fc8fcc44bd6a28ee

What gets me, what is trying to connect from 0.0.0.0:0?  I have never seen or heard of this address being used.


^ permalink raw reply	[relevance 0%]

* Re: Finding the end of a stream from a socket
  2017-10-21  8:44  0% ` Dmitry A. Kazakov
  2017-10-21 13:45  0%   ` Andrew Shvets
@ 2017-10-21 17:34  0%   ` Andrew Shvets
  2017-10-21 19:18  0%     ` Andrew Shvets
  1 sibling, 1 reply; 200+ results
From: Andrew Shvets @ 2017-10-21 17:34 UTC (permalink / raw)


On Saturday, October 21, 2017 at 4:44:42 AM UTC-4, Dmitry A. Kazakov wrote:
> On 2017-10-21 04:05, Andrew Shvets wrote:
> 
> > I've been recently trying to make a small TCP server (a toy.) I have
> > a channel that reads Characters and was trying to find the end of
> > the stream. Reading the documentation, I came across the following
> > in  g-socket.ads:
> > 
> > type Stream_Access is access all Ada.Streams.Root_Stream_Type'Class;
> > --  Same interface as Ada.Streams.Stream_IO
> > 
> > I was trying to have a way to find out when the last Character was 
> > read from the stream. I could catch the Ada.IO_Exceptions.End_Error 
> > exception, but I'm wondering if there is a better way.
> 
> End_Error is the best possible way, when applied. GNAT socket streams do 
> not raise End_Error, AFAIK.
> 
> > while not Ada.Streams.Stream_IO.End_Of_File(Channel) loop
> >    Character'Read(Channel, Received_Char);
> >    Ada.Text_IO.Put(Received_Char);
> > end loop;
> 
> This is a bad idea even when if it can work. In the case of sockets 
> there is no file end. When the connection is closed by the peer the 
> stream will stop both returning data and blocking. I suppose that will 
> cause Constraint_Error in Character'Read.
> 
> In practice there is a higher level protocol on top of the socket 
> stream, so that it is always known how many octets to read next.
> 
> Regarding your case, try this:
> 
>     Buffer : Stream_Element_Array (1..Buffer_Size);
>     Last   : Stream_Element_Offset;
> begin
>     loop
>        Receive_Socket (Socket, Buffer, Last);
>        exit when Last < Buffer'First; -- Connection is closed by the peer
>        for Octet in Buffer'First..Last loop -- Dump octets as-is
>           Put (Character'Val (Buffer (Octet)));
>        end loop;
>     end loop;
> 
> -- 
> Regards,
> Dmitry A. Kazakov
> http://www.dmitry-kazakov.de

Hi Dmitry,

This is my entire code.
https://gist.github.com/anonymous/b7c3a5bdcd8c78453a643b6785573131


^ permalink raw reply	[relevance 0%]

* Re: Finding the end of a stream from a socket
  2017-10-21  8:44  0% ` Dmitry A. Kazakov
@ 2017-10-21 13:45  0%   ` Andrew Shvets
  2017-10-21 17:34  0%   ` Andrew Shvets
  1 sibling, 0 replies; 200+ results
From: Andrew Shvets @ 2017-10-21 13:45 UTC (permalink / raw)


On Saturday, October 21, 2017 at 4:44:42 AM UTC-4, Dmitry A. Kazakov wrote:
> On 2017-10-21 04:05, Andrew Shvets wrote:
> 
> > I've been recently trying to make a small TCP server (a toy.) I have
> > a channel that reads Characters and was trying to find the end of
> > the stream. Reading the documentation, I came across the following
> > in  g-socket.ads:
> > 
> > type Stream_Access is access all Ada.Streams.Root_Stream_Type'Class;
> > --  Same interface as Ada.Streams.Stream_IO
> > 
> > I was trying to have a way to find out when the last Character was 
> > read from the stream. I could catch the Ada.IO_Exceptions.End_Error 
> > exception, but I'm wondering if there is a better way.
> 
> End_Error is the best possible way, when applied. GNAT socket streams do 
> not raise End_Error, AFAIK.
> 
> > while not Ada.Streams.Stream_IO.End_Of_File(Channel) loop
> >    Character'Read(Channel, Received_Char);
> >    Ada.Text_IO.Put(Received_Char);
> > end loop;
> 
> This is a bad idea even when if it can work. In the case of sockets 
> there is no file end. When the connection is closed by the peer the 
> stream will stop both returning data and blocking. I suppose that will 
> cause Constraint_Error in Character'Read.
> 
> In practice there is a higher level protocol on top of the socket 
> stream, so that it is always known how many octets to read next.
> 
> Regarding your case, try this:
> 
>     Buffer : Stream_Element_Array (1..Buffer_Size);
>     Last   : Stream_Element_Offset;
> begin
>     loop
>        Receive_Socket (Socket, Buffer, Last);
>        exit when Last < Buffer'First; -- Connection is closed by the peer
>        for Octet in Buffer'First..Last loop -- Dump octets as-is
>           Put (Character'Val (Buffer (Octet)));
>        end loop;
>     end loop;
> 
> -- 
> Regards,
> Dmitry A. Kazakov
> http://www.dmitry-kazakov.de

Thanks for your reply.  I did what you recommended.


  loop
    begin
      GNAT.Sockets.Receive_Socket(Receiver, Buffer, Last);

      -- the connection was reset by peer.
      exit when Last < Buffer'First;

      for Octet in Buffer'First .. Last loop
        Ada.Text_IO.Put(Character'Val(Buffer(Octet)));
      end loop;
    exception
      when Ada.IO_Exceptions.End_Error =>
        Ada.Text_IO.Put_Line(Ada.Text_IO.Standard_Error, " ERROR: Issue encountered while receiving data from user.");
    end;
  end loop;


I get the following error when I make the Receive_Socket procedure call:

raised GNAT.SOCKETS.SOCKET_ERROR : [107] Transport endpoint is not connected


^ permalink raw reply	[relevance 0%]

* Re: Finding the end of a stream from a socket
  2017-10-21  2:05  2% Finding the end of a stream from a socket Andrew Shvets
@ 2017-10-21  8:44  0% ` Dmitry A. Kazakov
  2017-10-21 13:45  0%   ` Andrew Shvets
  2017-10-21 17:34  0%   ` Andrew Shvets
  0 siblings, 2 replies; 200+ results
From: Dmitry A. Kazakov @ 2017-10-21  8:44 UTC (permalink / raw)


On 2017-10-21 04:05, Andrew Shvets wrote:

> I've been recently trying to make a small TCP server (a toy.) I have
> a channel that reads Characters and was trying to find the end of
> the stream. Reading the documentation, I came across the following
> in  g-socket.ads:
> 
> type Stream_Access is access all Ada.Streams.Root_Stream_Type'Class;
> --  Same interface as Ada.Streams.Stream_IO
> 
> I was trying to have a way to find out when the last Character was 
> read from the stream. I could catch the Ada.IO_Exceptions.End_Error 
> exception, but I'm wondering if there is a better way.

End_Error is the best possible way, when applied. GNAT socket streams do 
not raise End_Error, AFAIK.

> while not Ada.Streams.Stream_IO.End_Of_File(Channel) loop
>    Character'Read(Channel, Received_Char);
>    Ada.Text_IO.Put(Received_Char);
> end loop;

This is a bad idea even when if it can work. In the case of sockets 
there is no file end. When the connection is closed by the peer the 
stream will stop both returning data and blocking. I suppose that will 
cause Constraint_Error in Character'Read.

In practice there is a higher level protocol on top of the socket 
stream, so that it is always known how many octets to read next.

Regarding your case, try this:

    Buffer : Stream_Element_Array (1..Buffer_Size);
    Last   : Stream_Element_Offset;
begin
    loop
       Receive_Socket (Socket, Buffer, Last);
       exit when Last < Buffer'First; -- Connection is closed by the peer
       for Octet in Buffer'First..Last loop -- Dump octets as-is
          Put (Character'Val (Buffer (Octet)));
       end loop;
    end loop;

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

^ permalink raw reply	[relevance 0%]

* Finding the end of a stream from a socket
@ 2017-10-21  2:05  2% Andrew Shvets
  2017-10-21  8:44  0% ` Dmitry A. Kazakov
  0 siblings, 1 reply; 200+ results
From: Andrew Shvets @ 2017-10-21  2:05 UTC (permalink / raw)


Hello,

I've been recently trying to make a small TCP server (a toy.)  I have a channel that reads Characters and was trying to find the end of the stream.  Reading the documentation, I came across the following in g-socket.ads:


type Stream_Access is access all Ada.Streams.Root_Stream_Type'Class; 
--  Same interface as Ada.Streams.Stream_IO


I was trying to have a way to find out when the last Character was read from the stream.  I could catch the Ada.IO_Exceptions.End_Error exception, but I'm wondering if there is a better way.


Channel       : GNAT.Sockets.Stream_Access;

....

while not Ada.Streams.Stream_IO.End_Of_File(Channel) loop
  Character'Read(Channel, Received_Char);
  Ada.Text_IO.Put(Received_Char);
end loop;





Many thank yous in advance for your help!


^ permalink raw reply	[relevance 2%]

* Re: quiz for Sequential_IO Read
  2017-09-04 19:58  3%       ` Frank Buss
@ 2017-09-04 20:55  0%         ` Dmitry A. Kazakov
  0 siblings, 0 replies; 200+ results
From: Dmitry A. Kazakov @ 2017-09-04 20:55 UTC (permalink / raw)


On 2017-09-04 21:58, Frank Buss wrote:
> On 09/03/2017 03:11 PM, Dmitry A. Kazakov wrote:
>>
>> In practice Stream I/O is a better choice. You also should not use
>> compiler-generated serialization attributes (see T'Read, T'Write,
>> T'Input, T'Output attributes). These are not portable either. You should
>> always replace them with your own.
> 
> Ok, I wrote my program with Stream_IO. It will be reading from a FIFO 
> file for receiving MIDI signals, and then write to a sound device 
> continuously. I found a convenient package which defines low-level types 
> of fixed size, same as stdint.h in C. See below for the code. Would this 
> be portable on all systems (assuming they provide FIFO files) ?

You probably mean a pipe here?

> At least 
> it works on my Debian system so far.
> 
> 
> with Ada.Streams.Stream_IO; use Ada.Streams.Stream_IO;
> with Ada.Text_IO; use Ada.Text_IO;
> with Interfaces; use Interfaces;
> 
> procedure Hello is
> 
>     Data : Unsigned_8;
>     Input_File : Ada.Streams.Stream_IO.File_Type;
>     Input_Stream : Ada.Streams.Stream_IO.Stream_Access;
> 
>     task Main_Task is
>        entry Data_Received(Data : in Unsigned_8);
>     end Main_Task;
> 
>     task body Main_Task is
>     begin
>        loop
>           select
>              accept Data_Received(Data : in Unsigned_8) do
>                 Put("test: " & Unsigned_8'Image(Data));
>                 New_Line;
>              end Data_Received;
>           else
>              delay 0.1;

To avoid biased time error you should use "delay until" instead:

    delay until Last_Time + 0.1;
    Last_Time := Last_Time + 0.1;

And it is not a good idea to pass each octet to the task. A better 
design is to have a FIFO (ring buffer) to be filled by one task and read 
by another. It can be the same task as well.

>              -- TODO: create continuous sound output here
>           end select;
>        end loop;
>     end Main_Task;
> 
> begin
>     Open(Input_File, In_File, "/home/frank/midi");
>     Input_Stream := Stream(Input_File);
>     loop
>        Unsigned_8'Read(Input_Stream, Data);

Then you can read stream by pieces rather element by element. E.g.

    Buffer : Stream_Element_Array (1..Buffer_Size);
    Last   : Stream_Element_OFfset;
    ...

    Input_Stream.Read (Buffer, Last); -- Read available data
                                      -- Buffer (1..Last) is
                                      -- the data read

If you have FIFO to communicate with the task. It also can server as 
the input buffer. And you will simply read into the space between 
In_Index of the FIFO and either the FIFO's end index or Out_Index - 1, 
assuming FIFO is a ring buffer. You can use slice to do this:

    FIFO      : Stream_Element_Array (1..Buffer_Size);
    In_Index  : Stream_Element_Offset := 1; -- The index to write at
    Out_Index : Stream_Element_Offset := 1; -- The index to get data at

    ...
    if In_Index < Out_Index then
       Input_Stream.Read (FIFO (In_Index..Out_Index - 1), Last);
       In_Index := Last + 1;
    else
       Input_Stream.Read (FIFO (In_Index..FIFO'Last), Last);
       if Last = FIFO'Last then -- wrap
          In_Index := FIFO'First;
       else
          In_Index := Last + 1;
       end if;
    end if;

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

^ permalink raw reply	[relevance 0%]

* Re: quiz for Sequential_IO Read
  2017-09-03 13:11  0%     ` Dmitry A. Kazakov
@ 2017-09-04 19:58  3%       ` Frank Buss
  2017-09-04 20:55  0%         ` Dmitry A. Kazakov
  0 siblings, 1 reply; 200+ results
From: Frank Buss @ 2017-09-04 19:58 UTC (permalink / raw)


On 09/03/2017 03:11 PM, Dmitry A. Kazakov wrote:
>
> In practice Stream I/O is a better choice. You also should not use
> compiler-generated serialization attributes (see T'Read, T'Write,
> T'Input, T'Output attributes). These are not portable either. You should
> always replace them with your own.

Ok, I wrote my program with Stream_IO. It will be reading from a FIFO 
file for receiving MIDI signals, and then write to a sound device 
continuously. I found a convenient package which defines low-level types 
of fixed size, same as stdint.h in C. See below for the code. Would this 
be portable on all systems (assuming they provide FIFO files) ? At least 
it works on my Debian system so far.


with Ada.Streams.Stream_IO; use Ada.Streams.Stream_IO;
with Ada.Text_IO; use Ada.Text_IO;
with Interfaces; use Interfaces;

procedure Hello is

    Data : Unsigned_8;
    Input_File : Ada.Streams.Stream_IO.File_Type;
    Input_Stream : Ada.Streams.Stream_IO.Stream_Access;

    task Main_Task is
       entry Data_Received(Data : in Unsigned_8);
    end Main_Task;

    task body Main_Task is
    begin
       loop
          select
             accept Data_Received(Data : in Unsigned_8) do
                Put("test: " & Unsigned_8'Image(Data));
                New_Line;
             end Data_Received;
          else
             delay 0.1;
             -- TODO: create continuous sound output here
          end select;
       end loop;
    end Main_Task;

begin
    Open(Input_File, In_File, "/home/frank/midi");
    Input_Stream := Stream(Input_File);
    loop
       Unsigned_8'Read(Input_Stream, Data);
       Main_Task.Data_Received(Data);
    end loop;
end;


-- 
Frank Buss, http://www.frank-buss.de
electronics and more: http://www.youtube.com/user/frankbuss


^ permalink raw reply	[relevance 3%]

* Re: quiz for Sequential_IO Read
  2017-09-03 12:43  0%   ` Frank Buss
@ 2017-09-03 13:11  0%     ` Dmitry A. Kazakov
  2017-09-04 19:58  3%       ` Frank Buss
  0 siblings, 1 reply; 200+ results
From: Dmitry A. Kazakov @ 2017-09-03 13:11 UTC (permalink / raw)


On 2017-09-03 14:43, Frank Buss wrote:
> On 09/03/2017 02:26 PM, Dmitry A. Kazakov wrote:
>> On 2017-09-03 13:01, Frank Buss wrote:
>>> What does this program output?
>>
>> Garbage.
>>
>>> with Ada.Sequential_IO;
>>> with Ada.Text_IO; use Ada.Text_IO;
>>>
>>> procedure Hello is
>>>
>>>     type Byte is range 0..255;
>>>
>>>     package Byte_IO is new Ada.Sequential_IO(Byte);
>>
>> Ada.Streams.Stream_IO is for the purpose.
>>
>> (Sequential_IO is practically never used)
> 
> I started learning Ada today,

Great!

> where can I read about good coding 
> practice, and how would the example look like with Stream_IO, and maybe 
> even a correct version?
> 
> I read about Sequential_IO in the Ada Programming wikibook, where it is 
> recommended for homogeneous binary data:
> 
> https://en.wikibooks.org/wiki/Ada_Programming/Input_Output

Well, Sequential_IO is not recommended because:

1. It would make your program non-portable;
2. It would hinder interoperability with programs written on other 
languages;
3. It requires homogeneous data, which is never the case in real life
4. It limits I/O to files

In practice Stream I/O is a better choice. You also should not use 
compiler-generated serialization attributes (see T'Read, T'Write, 
T'Input, T'Output attributes). These are not portable either. You should 
always replace them with your own.

P.S. Sequential_IO was introduced in Ada 83. A lot of things changed 
since then.

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

^ permalink raw reply	[relevance 0%]

* Re: quiz for Sequential_IO Read
  2017-09-03 12:26  2% ` Dmitry A. Kazakov
@ 2017-09-03 12:43  0%   ` Frank Buss
  2017-09-03 13:11  0%     ` Dmitry A. Kazakov
  0 siblings, 1 reply; 200+ results
From: Frank Buss @ 2017-09-03 12:43 UTC (permalink / raw)


On 09/03/2017 02:26 PM, Dmitry A. Kazakov wrote:
> On 2017-09-03 13:01, Frank Buss wrote:
>> What does this program output?
>
> Garbage.
>
>> with Ada.Sequential_IO;
>> with Ada.Text_IO; use Ada.Text_IO;
>>
>> procedure Hello is
>>
>>     type Byte is range 0..255;
>>
>>     package Byte_IO is new Ada.Sequential_IO(Byte);
>
> Ada.Streams.Stream_IO is for the purpose.
>
> (Sequential_IO is practically never used)

I started learning Ada today, where can I read about good coding 
practice, and how would the example look like with Stream_IO, and maybe 
even a correct version?

I read about Sequential_IO in the Ada Programming wikibook, where it is 
recommended for homogeneous binary data:

https://en.wikibooks.org/wiki/Ada_Programming/Input_Output

-- 
Frank Buss, http://www.frank-buss.de
electronics and more: http://www.youtube.com/user/frankbuss

^ permalink raw reply	[relevance 0%]

* Re: quiz for Sequential_IO Read
  @ 2017-09-03 12:26  2% ` Dmitry A. Kazakov
  2017-09-03 12:43  0%   ` Frank Buss
  0 siblings, 1 reply; 200+ results
From: Dmitry A. Kazakov @ 2017-09-03 12:26 UTC (permalink / raw)


On 2017-09-03 13:01, Frank Buss wrote:
> What does this program output?

Garbage.

> with Ada.Sequential_IO;
> with Ada.Text_IO; use Ada.Text_IO;
> 
> procedure Hello is
> 
>     type Byte is range 0..255;
> 
>     package Byte_IO is new Ada.Sequential_IO(Byte);

Ada.Streams.Stream_IO is for the purpose.

(Sequential_IO is practically never used)

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

^ permalink raw reply	[relevance 2%]

* Re: win32 interfacing check (SetClipboardData)
  2017-09-02  9:38  0%           ` Xavier Petit
@ 2017-09-02 12:29  0%             ` Dmitry A. Kazakov
  0 siblings, 0 replies; 200+ results
From: Dmitry A. Kazakov @ 2017-09-02 12:29 UTC (permalink / raw)


On 2017-09-02 11:38, Xavier Petit wrote:
> Le 01/09/2017 à 15:10, Dmitry A. Kazakov a écrit :
>> On 01/09/2017 14:51, Xavier Petit wrote:
>>> Thanks but even with Set_Clipboard 
>>> (Ada.[Wide_]Wide_Text_IO.Get_Line); I was getting weird clipboard 
>>> text without -gnatW8 flag.
>>
>> But these are not UTF-8! They are UCS-2 and UCS-4.
> Yes but having a look at :
> https://gcc.gnu.org/onlinedocs/gnat_ugn/Character-Set-Control.html
> https://gcc.gnu.org/onlinedocs/gnat_ugn/Wide_005fCharacter-Encodings.html
> https://gcc.gnu.org/onlinedocs/gnat_ugn/Wide_005fWide_005fCharacter-Encodings.html 

These about the source code encoding not about run-time I/O.

> So it means Get_Line returns a Wide_Wide_String without the USC-4 
> encoding ? because Encode doesn't return UTF-(8/16) encoding without the 
> flag.

It depends on the input file. Get_Line will work only if the text file 
you are reading from is UCS-4 encoded. Where did you get such files?

AFAIK, GNAT implementation supports the Form parameter in Open, where 
you can specify the file encoding if that is different from the string 
encoding, e.g. UTF-8 when Wide_Wide_Text_IO deals with UCS-4. I suppose 
that should recode the input into the designated string encoding. 
However I never tried this and do not intend to.

>> If you have a UTF-8 encoded file (e.g. created using Notepad++, saved 
>> without BOM), you should use Ada.Streams.Stream_IO, best in binary 
>> mode if you are using GNAT.
>>
>> You will have to detect line ends manually, but at least there will be 
>> guaranty that the run-time does not mangle anything.
> Ok, “binary mode”, do you mean using Stream_Element_Array ?
> 
>> If you are using Windows calls with the "W" suffix, then all strings 
>> there are already UTF-16 and you don't need to convert anything.
> Ok, if I stay with win32 functions, I'll get only UTF-16, if I mess with 
> external text sources (like files) or Ada standard, I'll deal with 
> others text encoding formats like UTF-8, UCS-2, etc...

When dealing with external files I read them using Stream_IO and recode 
manually to UTF-8 if necessary. Luckily in the recent time the supply of 
files encoded in Latin-1, UCS-2 and other increasingly idiotic formats 
is almost depleted. So there is little to worry about...

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


^ permalink raw reply	[relevance 0%]

* Re: win32 interfacing check (SetClipboardData)
  2017-09-01 13:10  2%         ` Dmitry A. Kazakov
@ 2017-09-02  9:38  0%           ` Xavier Petit
  2017-09-02 12:29  0%             ` Dmitry A. Kazakov
  0 siblings, 1 reply; 200+ results
From: Xavier Petit @ 2017-09-02  9:38 UTC (permalink / raw)


Le 01/09/2017 à 15:10, Dmitry A. Kazakov a écrit :
> On 01/09/2017 14:51, Xavier Petit wrote:
>> Thanks but even with Set_Clipboard (Ada.[Wide_]Wide_Text_IO.Get_Line); 
>> I was getting weird clipboard text without -gnatW8 flag.
> 
> But these are not UTF-8! They are UCS-2 and UCS-4.
Yes but having a look at :
https://gcc.gnu.org/onlinedocs/gnat_ugn/Character-Set-Control.html
https://gcc.gnu.org/onlinedocs/gnat_ugn/Wide_005fCharacter-Encodings.html
https://gcc.gnu.org/onlinedocs/gnat_ugn/Wide_005fWide_005fCharacter-Encodings.html

It appears that without the -gnatW8 flag, "Brackets Coding" is the default :
- “In this encoding, a wide character is represented by the following 
eight character sequence: [...]”
- “In this encoding, a wide wide character is represented by the 
following ten or twelve byte character sequence”

...and with the flag, "UTF-8 Coding" is used : “A wide character is 
represented using UCS Transformation Format 8 (UTF-8)”

I think I'm still missing something because one thing is sure :
Ada.Strings.UTF_Encoding.Wide_Wide_String.Encode 
(Ada.Wide_Wide_Text_IO.Get_Line) doesn't not work without the UTF-8 flag...

 From UTF_Encoding.Wide_Wide_Strings package :
“
The encoding routines take a Wide_Wide_String as input and encode the
result using the specified UTF encoding method.
Encode Wide_Wide_String using UTF-8 encoding
Encode Wide_Wide_String using UTF_16 encoding
”
So it means Get_Line returns a Wide_Wide_String without the USC-4 
encoding ? because Encode doesn't return UTF-(8/16) encoding without the 
flag.

> ([Wide_]Wide_Text_IO should never be used, there is no single case one 
> would need these.)
yeah I'm gonna try not to use the Wide_Wide packages, one thing I liked 
with Wide_Wide_String is the correct 'Length attribute.

> If you have a UTF-8 encoded file (e.g. created using Notepad++, saved 
> without BOM), you should use Ada.Streams.Stream_IO, best in binary mode 
> if you are using GNAT.
> 
> You will have to detect line ends manually, but at least there will be 
> guaranty that the run-time does not mangle anything.
Ok, “binary mode”, do you mean using Stream_Element_Array ?

> If you are using Windows calls with the "W" suffix, then all strings 
> there are already UTF-16 and you don't need to convert anything.
Ok, if I stay with win32 functions, I'll get only UTF-16, if I mess with 
external text sources (like files) or Ada standard, I'll deal with 
others text encoding formats like UTF-8, UCS-2, etc...

^ permalink raw reply	[relevance 0%]

* Re: win32 interfacing check (SetClipboardData)
  @ 2017-09-01 13:10  2%         ` Dmitry A. Kazakov
  2017-09-02  9:38  0%           ` Xavier Petit
  0 siblings, 1 reply; 200+ results
From: Dmitry A. Kazakov @ 2017-09-01 13:10 UTC (permalink / raw)


On 01/09/2017 14:51, Xavier Petit wrote:
> Thanks but even with Set_Clipboard (Ada.[Wide_]Wide_Text_IO.Get_Line); I 
> was getting weird clipboard text without -gnatW8 flag.

But these are not UTF-8! They are UCS-2 and UCS-4.

([Wide_]Wide_Text_IO should never be used, there is no single case one 
would need these.)

If you have a UTF-8 encoded file (e.g. created using Notepad++, saved 
without BOM), you should use Ada.Streams.Stream_IO, best in binary mode 
if you are using GNAT.

You will have to detect line ends manually, but at least there will be 
guaranty that the run-time does not mangle anything.

If you are using Windows calls with the "W" suffix, then all strings 
there are already UTF-16 and you don't need to convert anything.

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


^ permalink raw reply	[relevance 2%]

* Re: zLibAda vs ZipAda (which should I use, if any)?
    @ 2016-08-27 19:33  3% ` Aurele
  1 sibling, 0 replies; 200+ results
From: Aurele @ 2016-08-27 19:33 UTC (permalink / raw)


Thanks, was just looking at your To_Bmp demo and also noticed you had txt file (which I should have seen/read first).  So the steps are fairly straight forward....

1) Load the image header from stream
2) Prepare the retrieval of the image ?
3) Load/decode the image itself

Sounds easy. Thanks!

I have not check/looked yest but is the Zip-Ada "UnZip.Streams.Zipped_File_Type" type a subtype of "Ada.Streams.Stream_IO.File_Type" ? 

In otherwords, if I have:

 UnZip.Streams.Open( File         => FileType,
                     Archive_Info => ZipFileInfo,
                     Name         => ASU.To_String( Info_Ptr.Data_Ptr( 31 ).FullName ) );

can I user 

Ada.Streams.Stream_IO.Stream_Access( UnZip.Streams.Stream( FileType ) )

When in calling GID.Load_image_header( .....) ?



^ permalink raw reply	[relevance 3%]

* Re: zLibAda vs ZipAda (which should I use, if any)?
  2016-08-27 16:31  2%                         ` Aurele
@ 2016-08-27 19:15  0%                           ` gautier_niouzes
  0 siblings, 0 replies; 200+ results
From: gautier_niouzes @ 2016-08-27 19:15 UTC (permalink / raw)


Le samedi 27 août 2016 18:31:30 UTC+2, Aurele a écrit :
> Hi Gautier, I think your GID packages will provide the services I need. Very well done by the way.  
> 
> Maybe you can save me some time and guide me on its use for my needs.  I've inserted some code below that show how I'll load the images from the zip file using Zip-Ada, I arrange the data (not shown), and then I need to call GID procedure to load as Handle.
> 
> Any comments or ideas? 
> 
> declare
> 
>   package ASU renames Ada.Strings.Unbounded;
> 
>   type Entry_ID is new Integer range -1..Integer'Last;
> 
>   type iEntry is record
>     Texture_ID : ZipFile.Entry_ID;
>     FullName   : Ada.Strings.Unbounded.Unbounded_String;
>     Directory  : Ada.Strings.Unbounded.Unbounded_String;
>     EntryName  : Ada.Strings.Unbounded.Unbounded_String;
>     Extension  : Ada.Strings.Unbounded.Unbounded_String;
>   end record;
>   type iEntryEntry_Ptr is access all ZipFile.iEntry;
> 
>   subtype iEntry_Array_Size is Entry_ID;
> 
>   type iEntry_Array is array ( iEntry_Array_Size range <> ) of aliased ZipFile.iEntry;
>   type iEntry_Array_Ptr is access all ZipFile.iEntry_Array;
> 
>   type Information is record
>     File_Location   : Ada.Strings.Unbounded.Unbounded_String;
>     File_Name       : Ada.Strings.Unbounded.Unbounded_String;
>     Total_Entries   : Natural;
>     Texture_Entries : Natural;
>     Data_Ptr        : ZipFile.iEntry_Array_Ptr;
>   end record;
>   type Information_Ptr is access all ZipFile.Information;
> 
>   Zip_File_Name         : constant String := "Textures.zip";
>   Zip_File_Entries      : iEntry_Array_Size;
> 
>   lpTexture_Array       : aliased iEntry_Array_Ptr;
>   lpTexture_Info        : aliased Information_Ptr
> 
>   Local_Index           : Entry_ID;
> 
>   ZipFileInfo           : Zip.Zip_Info;
>   FileType              : UnZip.Streams.Zipped_File_Type;
> 
> -----------------------------------------------------------------
> begin
> 
>   Zip.Load( ZipFileInfo, Zip_File_Name );
> 
>   Zip_File_Entries := iEntry_Array_Size( Zip.Entries( ZipFileInfo ) );
> 
>   lpTexture_Array  := new ZipFile.iEntry_Array( 1..Zip_File_Entries );
>   lpTexture_Info   := new ZipFile.Information;
> 
>   -- Scan procedure not shown here but is straight forward...
>   Scan( ZipFileInfo, FileName, Info_Ptr ); -- FILL INFO_PTR
> 
>   -- Simple test....  try to retrieve an image at index = 10
> 
>   Local_Index := 10; -- TEST: image at index = 10
> 
>   UnZip.Streams.Open
>     ( File         => FileType,
>       Archive_Info => ZipFileInfo,
>       Name  => ASU.To_String( Info_Ptr.Data_Ptr( Local_Index ).FullName ) 
>      );
> 
>   -- ???????????????????????????????????????????????????????
>   -- LoadImage is below, no idea yet what has to be done
> 
>   LoadImage( FileNeme => Info_Ptr.Data_Ptr( Local_Index ).EntryName,
>              FileExt  => Info_Ptr.Data_Ptr( Local_Index ).Extension,
>              FullName => Ada.Streams.Stream_IO.Stream_Access( UnZip.Streams.Stream( FileType ) ) );
> 
>   UnZip.Streams.Close( FileType );
> 
> end;
> 
> 
> -----------------------------------------------------------------
> - TBD: Call "GID" procedure to load image (DIB or BMP (bitmap))
> 
> type Hande is access all System.Address;  
> hBitmap : Hande := NULL;
> 
> procedure LoadImage ( FileName : Ada.Strings.Unbounded.Unbounded_String;
>                       FileExt  : Ada.Strings.Unbounded.Unbounded_String;
>                       FullName : Ada.Strings.Unbounded.Unbounded_String ) is
> begin
>                    -- --------------------------
>   hBitmap := ?;    -- Call GID directly here ??? Steps ????
>                    -----------------------------
> end LoadImage;
> 
> -----------------------------------------------------------------
> 
> Cheers and thanks
> Aurele

I'm just copy-pasting useful things from the To_BMP example, which will be ok for a Windows bitmap. I skip the image rotation stuff to simplify...

  type Byte_Array is array(Integer range <>) of Unsigned_8;
  type p_Byte_Array is access Byte_Array;
  procedure Dispose is new Ada.Unchecked_Deallocation(Byte_Array, p_Byte_Array);

  img_buf: p_Byte_Array:= null;

  procedure Load_raw_image(
    image : in out GID.Image_descriptor;
    buffer: in out p_Byte_Array
  )
  is
    subtype Primary_color_range is Unsigned_8;
    subtype U16 is Unsigned_16;
    image_width: constant Positive:= GID.Pixel_width(image);
    image_height: constant Positive:= GID.Pixel_height(image);
    padded_line_size_x: constant Positive:=
      4 * Integer(Float'Ceiling(Float(image_width) * 3.0 / 4.0));
    padded_line_size_y: constant Positive:=
      4 * Integer(Float'Ceiling(Float(image_height) * 3.0 / 4.0));
    -- (in bytes)
    idx: Integer;
    --
    procedure Set_X_Y (x, y: Natural) is
    pragma Inline(Set_X_Y);
    begin
      idx:= 3 * x + padded_line_size_x * y;
    end Set_X_Y;
    --
    procedure Put_Pixel_without_bkg (
      red, green, blue : Primary_color_range;
      alpha            : Primary_color_range
    )
    is
    pragma Inline(Put_Pixel_without_bkg);
    pragma Warnings(off, alpha); -- alpha is just ignored
    begin
      buffer(idx..idx+2):= (blue, green, red);
      -- GID requires us to look to next pixel for next time:
      idx:= idx + 3;
    end Put_Pixel_without_bkg;
    --
    procedure BMP24_Load_without_bkg is
      new GID.Load_image_contents(
        Primary_color_range,
        Set_X_Y,
        Put_Pixel_without_bkg,
        Feedback,
        GID.fast
      );
    next_frame: Ada.Calendar.Day_Duration;
  begin
    Dispose(buffer);
    buffer:= new Byte_Array(0..padded_line_size_x * GID.Pixel_height(image) - 1);
    BMP24_Load_without_bkg(image, next_frame);
  end Load_raw_image;

...
    i: GID.Image_descriptor;
  begin
    GID.Load_image_header(i, Your_nice_stream_Access.all, True);
    Load_raw_image(i, img_buf);
  end;

Now you surely know better how to let the image buffer (img_buf) meet the hBitmap handle (some Windows-ish bureaucracy ;-) )
_________________________ 
Gautier's Ada programming 
http://gautiersblog.blogspot.com/search/label/Ada 
NB: follow the above link for a valid e-mail address 

^ permalink raw reply	[relevance 0%]

* Re: zLibAda vs ZipAda (which should I use, if any)?
  @ 2016-08-27 16:31  2%                         ` Aurele
  2016-08-27 19:15  0%                           ` gautier_niouzes
  0 siblings, 1 reply; 200+ results
From: Aurele @ 2016-08-27 16:31 UTC (permalink / raw)


Hi Gautier, I think your GID packages will provide the services I need. Very well done by the way.  

Maybe you can save me some time and guide me on its use for my needs.  I've inserted some code below that show how I'll load the images from the zip file using Zip-Ada, I arrange the data (not shown), and then I need to call GID procedure to load as Handle.

Any comments or ideas? 

declare

  package ASU renames Ada.Strings.Unbounded;

  type Entry_ID is new Integer range -1..Integer'Last;

  type iEntry is record
    Texture_ID : ZipFile.Entry_ID;
    FullName   : Ada.Strings.Unbounded.Unbounded_String;
    Directory  : Ada.Strings.Unbounded.Unbounded_String;
    EntryName  : Ada.Strings.Unbounded.Unbounded_String;
    Extension  : Ada.Strings.Unbounded.Unbounded_String;
  end record;
  type iEntryEntry_Ptr is access all ZipFile.iEntry;

  subtype iEntry_Array_Size is Entry_ID;

  type iEntry_Array is array ( iEntry_Array_Size range <> ) of aliased ZipFile.iEntry;
  type iEntry_Array_Ptr is access all ZipFile.iEntry_Array;

  type Information is record
    File_Location   : Ada.Strings.Unbounded.Unbounded_String;
    File_Name       : Ada.Strings.Unbounded.Unbounded_String;
    Total_Entries   : Natural;
    Texture_Entries : Natural;
    Data_Ptr        : ZipFile.iEntry_Array_Ptr;
  end record;
  type Information_Ptr is access all ZipFile.Information;

  Zip_File_Name         : constant String := "Textures.zip";
  Zip_File_Entries      : iEntry_Array_Size;

  lpTexture_Array       : aliased iEntry_Array_Ptr;
  lpTexture_Info        : aliased Information_Ptr

  Local_Index           : Entry_ID;

  ZipFileInfo           : Zip.Zip_Info;
  FileType              : UnZip.Streams.Zipped_File_Type;

-----------------------------------------------------------------
begin

  Zip.Load( ZipFileInfo, Zip_File_Name );

  Zip_File_Entries := iEntry_Array_Size( Zip.Entries( ZipFileInfo ) );

  lpTexture_Array  := new ZipFile.iEntry_Array( 1..Zip_File_Entries );
  lpTexture_Info   := new ZipFile.Information;

  -- Scan procedure not shown here but is straight forward...
  Scan( ZipFileInfo, FileName, Info_Ptr ); -- FILL INFO_PTR

  -- Simple test....  try to retrieve an image at index = 10

  Local_Index := 10; -- TEST: image at index = 10

  UnZip.Streams.Open
    ( File         => FileType,
      Archive_Info => ZipFileInfo,
      Name  => ASU.To_String( Info_Ptr.Data_Ptr( Local_Index ).FullName ) 
     );

  -- ???????????????????????????????????????????????????????
  -- LoadImage is below, no idea yet what has to be done

  LoadImage( FileNeme => Info_Ptr.Data_Ptr( Local_Index ).EntryName,
             FileExt  => Info_Ptr.Data_Ptr( Local_Index ).Extension,
             FullName => Ada.Streams.Stream_IO.Stream_Access( UnZip.Streams.Stream( FileType ) ) );

  UnZip.Streams.Close( FileType );

end;


-----------------------------------------------------------------
- TBD: Call "GID" procedure to load image (DIB or BMP (bitmap))

type Hande is access all System.Address;  
hBitmap : Hande := NULL;

procedure LoadImage ( FileName : Ada.Strings.Unbounded.Unbounded_String;
                      FileExt  : Ada.Strings.Unbounded.Unbounded_String;
                      FullName : Ada.Strings.Unbounded.Unbounded_String ) is
begin
                   -- --------------------------
  hBitmap := ?;    -- Call GID directly here ??? Steps ????
                   -----------------------------
end LoadImage;

-----------------------------------------------------------------

Cheers and thanks
Aurele


^ permalink raw reply	[relevance 2%]

* Re: How to write "Hello" to a text file without a line terminator
  2016-08-14  9:40  2%                     ` Simon Wright
@ 2016-08-14 10:17  2%                       ` Dmitry A. Kazakov
  0 siblings, 0 replies; 200+ results
From: Dmitry A. Kazakov @ 2016-08-14 10:17 UTC (permalink / raw)


On 2016-08-14 11:40, Simon Wright wrote:

> I am saying that (it seems to me that) it is impossible to read back
> from Sequential_IO with an unconstrained type even on the same machine
> with the same compiler.

You can through S'Input. Read is just a wrapper for S'Read, it could 
have been omitted too.

And regarding the design it should have been:

package Ada.Streams is
    type Abstract_Root_Stream_Type is limited interface;
    type Root_Stream_Type is new Abstract_Root_Stream_Type with private;

...
package Ada.Streams.Stream_IO is
    type File_Type is new Abstract_Root_Stream_Type with private;

and no

function Stream (File : in File_Type) return Stream_Access;

>> All that needed is pragma Assert that Stream_Element'Size = 8 and
>> Stream_Element_Array I/O.
>
> Ada.Streams.Stream_IO & String'Write is even simpler in 99.9% of cases.

Yes, when String'Component_Size = Stream_Element_Size = 8.

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

^ permalink raw reply	[relevance 2%]

* Re: How to write "Hello" to a text file without a line terminator
  @ 2016-08-14  9:40  2%                     ` Simon Wright
  2016-08-14 10:17  2%                       ` Dmitry A. Kazakov
  0 siblings, 1 reply; 200+ results
From: Simon Wright @ 2016-08-14  9:40 UTC (permalink / raw)


"Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> writes:

> On 2016-08-14 10:30, Simon Wright wrote:
>
>> Come to think of it, what would the use case be for instantiating
>> Sequential (or Direct) IO with an unconstrained type?
>
> Direct_IO requires a constrained type.

So it does. And Sequential_IO explicitly permists an unconstrained
type. Still,

>> they both have
>> only procedural forms for Read, so how could you ever retrieve a value?
>
> Does it matter? It is not portable to use anyway.

I am saying that (it seems to me that) it is impossible to read back
from Sequential_IO with an unconstrained type even on the same machine
with the same compiler.

> All that needed is pragma Assert that Stream_Element'Size = 8 and
> Stream_Element_Array I/O.

Ada.Streams.Stream_IO & String'Write is even simpler in 99.9% of cases.


^ permalink raw reply	[relevance 2%]

* Re: Out_File , excess line
  @ 2016-01-31 12:57  3%     ` Dmitry A. Kazakov
  0 siblings, 0 replies; 200+ results
From: Dmitry A. Kazakov @ 2016-01-31 12:57 UTC (permalink / raw)


On 2016-01-31 12:25, Simon Wright wrote:

> The standard solution to copying a file would be
>
>     with Ada.Text_IO; use Ada.Text_IO;

No, that does not copy a file. That 1) interprets a file context as a 
text file specific to the given operating system and then 2) writes the 
interpretation into another file. So it is a file conversion.

One solution to copy a file is using Copy_File from Ada.Directories.

Another is using Ada.Streams.Stream_IO. Both are not ideal but will work 
in most cases.

E.g. your example with Ada.Streams.Stream_IO:

  with Ada.Exceptions;        use Ada.Exceptions;
  with Ada.Streams;           use Ada.Streams;
  with Ada.Streams.Stream_IO; use Ada.Streams.Stream_IO;

  with Ada.Text_IO;

  procedure Fanzine is
     Buffer_Size : constant := 1024; -- Or more
     Input_File  : File_Type;
     Output_File : File_Type;
     Buffer      : Stream_Element_Array (1..Buffer_Size);
     Last        : Stream_Element_Offset;
     Count       : Stream_Element_Count := 0;
  begin
     Open (Input_File, In_File, "fanzine.adb");
     begin
        Create (Output_File, Out_File, "fanzine.adb.copy");
        loop
           Read (Input_File, Buffer, Last);
           exit when Last < Buffer'First;
           Count := Count + Last;
           Write (Output_File, Buffer (Buffer'First..Last));
       end loop;
    exception
       when End_Error =>
          null; -- Never here
    end;
    Close (Output_File);
    Close (Input_File);
    Ada.Text_IO.Put_Line
    (  "Written" & Stream_Element_Count'Image (Count) & " elements"
    );
exception
    when Error : others =>
       Ada.Text_IO.Put_Line ("Error " & Exception_Information (Error));
end Fanzine;

It is quite simple, if necessary, to detect line ends in a manner 
compatible with both Windows and Linux systems, given fixed encoding.

(Doing that independently of the encoding would probably be impossible, 
but who cares?)

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

^ permalink raw reply	[relevance 3%]

* Re: Out_File , excess line
  2016-01-27  9:26  0%   ` Simon Wright
@ 2016-01-27 20:28  0%     ` Dmitry A. Kazakov
  0 siblings, 0 replies; 200+ results
From: Dmitry A. Kazakov @ 2016-01-27 20:28 UTC (permalink / raw)


On 2016-01-27 10:26, Simon Wright wrote:
> comicfanzine@gmail.com writes:
>
>> But , when we try to open the file manually , the text editor print :
>>
>> " This is not a text file . Type unknown ."
>>     PACKAGE ST_IO RENAMES Ada.Streams.Stream_IO ;
>>
>>     test_file : ST_IO.File_type ;
>>
>>     Input_Stream : ST_IO.Stream_Access ;
> [...]
>>     ST_IO.Create( File => test_file ,
>>                 Mode => ST_IO.Out_File ,
>>                 Name => "test" );
>>
>>      Input_Stream := ST_IO.Stream( test_file );
>>
>>      for j in 1..case_array'Length loop
>>        Unbounded_String'Write( Input_Stream , case_array(j) );
>>     end loop;
>
> 'Input_Stream' is a very odd name for a stream you're going to *output*
> to.
>
> What's happening is that (reasonably, though not as far as I can see
> discussed by the standard) GNAT treats Unbounded_String'Write as if an
> unbounded string is a discriminated type whose discriminants have
> defaults; that is, the discriminants (the array bounds) are output to
> the stream first, followed by the characters of the string. (This is
> what happens for String'Output; String'Write doesn't include the bounds;
> is the Unbounded_String'Write behaviour a bug or a feature?).
>
> So, if you Unbounded_String'Write "foo", you will get
> - 4 bytes containing binary 1, the first index of the content
> - 4 bytes containing binary 3, the last index of the content
> - 3 bytes of content, 'f' 'o' 'o'.
>
> Which looks nothing like a text file.
>
> You could try
>
>    String'Write (Input_Stream, To_String (case_array (j)) & ASCII.LF);

This one of many reasons why no Unbounded_String should ever be used for 
any text processing. That includes text buffers of course. Using 
standard containers of Unbounded_String is probably least efficient 
possible way to implement a text buffer.

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

^ permalink raw reply	[relevance 0%]

* Re: Out_File , excess line
  2016-01-23 20:06  2% ` comicfanzine
@ 2016-01-27  9:26  0%   ` Simon Wright
  2016-01-27 20:28  0%     ` Dmitry A. Kazakov
  0 siblings, 1 reply; 200+ results
From: Simon Wright @ 2016-01-27  9:26 UTC (permalink / raw)


comicfanzine@gmail.com writes:

> But , when we try to open the file manually , the text editor print :
>
> " This is not a text file . Type unknown . "
>    PACKAGE ST_IO RENAMES Ada.Streams.Stream_IO ;
>
>    test_file : ST_IO.File_type ;
>
>    Input_Stream : ST_IO.Stream_Access ;
[...]
>    ST_IO.Create( File => test_file ,
>                Mode => ST_IO.Out_File ,
>                Name => "test" );
>
>     Input_Stream := ST_IO.Stream( test_file );
>
>     for j in 1..case_array'Length loop
>       Unbounded_String'Write( Input_Stream , case_array(j) );
>    end loop;

'Input_Stream' is a very odd name for a stream you're going to *output*
to.

What's happening is that (reasonably, though not as far as I can see
discussed by the standard) GNAT treats Unbounded_String'Write as if an
unbounded string is a discriminated type whose discriminants have
defaults; that is, the discriminants (the array bounds) are output to
the stream first, followed by the characters of the string. (This is
what happens for String'Output; String'Write doesn't include the bounds;
is the Unbounded_String'Write behaviour a bug or a feature?).

So, if you Unbounded_String'Write "foo", you will get
- 4 bytes containing binary 1, the first index of the content
- 4 bytes containing binary 3, the last index of the content
- 3 bytes of content, 'f' 'o' 'o'.

Which looks nothing like a text file.

You could try

  String'Write (Input_Stream, To_String (case_array (j)) & ASCII.LF);

(should be OK on Unix systems, don't know about Windows. A text
editor should be OK with LF-terminated lines, Notepad not so much.)

[1] http://www.ada-auth.org/standards/12rm/html/RM-13-13-2.html#p9.1

^ permalink raw reply	[relevance 0%]

* Re: Out_File , excess line
    2016-01-22 20:01  2% ` comicfanzine
@ 2016-01-23 20:06  2% ` comicfanzine
  2016-01-27  9:26  0%   ` Simon Wright
    2 siblings, 1 reply; 200+ results
From: comicfanzine @ 2016-01-23 20:06 UTC (permalink / raw)


I figured out how to use the package ?

The code compile , and is launchable too .

But , when we try to open the file manually , the text editor print :

" This is not a text file . Type unknown . "

Same information for the file manager( Thunar ) .

??

---------------
WITH Ada.Text_IO.Unbounded_IO ; USE Ada.Text_IO.Unbounded_IO ;
WITH Ada.Strings.Unbounded ;    USE Ada.Strings.Unbounded ;
WITH Ada.Text_IO  ;             USE Ada.Text_IO  ;
WITH Ada.Streams.Stream_IO ;

Procedure count_nb_lines is

  this_file : File_type ;

  count_line : integer := 0 ;

Begin

    Open
     (File => this_file ,
      Mode => In_file ,
      Name => "count_nb_lines.adb");

   loop exit when End_Of_File( this_file );
     skip_line( this_file );
     count_line := count_line + 1 ;
   end loop ;


   declare

   Type Tableau_file is array( 1 .. count_line) of Unbounded_String ;

   case_array : Tableau_file ;


   PACKAGE ST_IO RENAMES Ada.Streams.Stream_IO ;

   test_file : ST_IO.File_type ;

   Input_Stream : ST_IO.Stream_Access ;

   begin

   Reset( this_file );

    Loop exit when End_Of_File( this_file );
        for i in 1..case_array'Length loop
         case_array(i) := get_line(this_file);
       end loop ;
   End loop;

   ST_IO.Create( File => test_file ,
               Mode => ST_IO.Out_File ,
               Name => "test" );

    Input_Stream := ST_IO.Stream( test_file );

    for j in 1..case_array'Length loop
      Unbounded_String'Write( Input_Stream , case_array(j) );
   end loop;

    end;
End count_nb_lines ;




^ permalink raw reply	[relevance 2%]

* Re: Out_File , excess line
  @ 2016-01-22 20:01  2% ` comicfanzine
  2016-01-23 20:06  2% ` comicfanzine
    2 siblings, 0 replies; 200+ results
From: comicfanzine @ 2016-01-22 20:01 UTC (permalink / raw)


I'm working with a text file .

Now , i use the package Ada.Text_IO.Unbounded_IO for text in Unbounded_Strings .

If i use the package Ada.Streams.Stream_IO , instead of Ada.Text_IO , for text handling , there is some changes to do :

Is there a Unbounded_String package for Stream_IO  ?

Or a another simplier way ?
-----------------------
WITH Ada.Text_IO.Unbounded_IO ; USE Ada.Text_IO.Unbounded_IO ;
WITH Ada.Strings.Unbounded ;    USE Ada.Strings.Unbounded ;
WITH Ada.Text_IO  ;             USE Ada.Text_IO  ;

Procedure count_nb_lines is

  this_file , test_file : File_type ;

  count : integer := 0 ;

Begin

    Open
     (File => this_file ,
      Mode => In_file ,
      Name => "count_nb_lines.adb");

   loop exit when End_Of_File( this_file );
     skip_line( this_file );
     count := count + 1 ;
   end loop ;

   Open
     (File => test_file ,
      Mode => Out_File ,
      Name => "test.adb");

   declare

   Type Tableau_lines_file is array( 1 .. count) of Unbounded_String;

   case_array : Tableau_lines_file ;

   begin

   Reset( this_file );

    Loop exit when End_Of_File( this_file );
        for i in 1..case_array'Length loop
         case_array(i) := get_line(this_file);
       end loop ;
   End loop;

    for j in 1..case_array'Length loop
      put_line( test_file , case_array(j) );
   end loop;

    end;
End count_nb_lines ;


^ permalink raw reply	[relevance 2%]

* Re: Creating an empty file with Ada.Text_IO
  2015-08-25 15:26  0%     ` Maciej Sobczak
  2015-08-25 16:18  0%       ` J-P. Rosen
@ 2015-08-25 16:45  3%       ` G.B.
  1 sibling, 0 replies; 200+ results
From: G.B. @ 2015-08-25 16:45 UTC (permalink / raw)


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;

^ permalink raw reply	[relevance 3%]

* Re: Creating an empty file with Ada.Text_IO
  2015-08-25 15:26  0%     ` Maciej Sobczak
@ 2015-08-25 16:18  0%       ` J-P. Rosen
  2015-08-25 16:45  3%       ` G.B.
  1 sibling, 0 replies; 200+ results
From: J-P. Rosen @ 2015-08-25 16:18 UTC (permalink / raw)


Le 25/08/2015 17:26, Maciej Sobczak a écrit :
>> 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;
Or simply:
      A : Ada.Streams.Stream_Element_Array
         (Stream_Element_Offset(S'First) ..
          Stream_Element_Offset(S'Last));

(saves some computation in the loop)
-- 
J-P. Rosen
Adalog
2 rue du Docteur Lombard, 92441 Issy-les-Moulineaux CEDEX
Tel: +33 1 45 29 21 52, Fax: +33 1 45 29 25 00
http://www.adalog.fr

^ permalink raw reply	[relevance 0%]

* Re: Creating an empty file with Ada.Text_IO
  2015-08-25  8:20  3%   ` Maciej Sobczak
@ 2015-08-25 15:26  0%     ` Maciej Sobczak
  2015-08-25 16:18  0%       ` J-P. Rosen
  2015-08-25 16:45  3%       ` G.B.
  0 siblings, 2 replies; 200+ results
From: Maciej Sobczak @ 2015-08-25 15:26 UTC (permalink / raw)



>    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.)

-- 
Maciej Sobczak * http://www.inspirel.com

^ permalink raw reply	[relevance 0%]

* Re: Creating an empty file with Ada.Text_IO
  @ 2015-08-25  8:20  3%   ` Maciej Sobczak
  2015-08-25 15:26  0%     ` Maciej Sobczak
  0 siblings, 1 reply; 200+ results
From: Maciej Sobczak @ 2015-08-25  8:20 UTC (permalink / raw)


> > What are the recommended ways of:
> > a) creating empty files
> > b) writing a non-terminated line to (or generally at the end of) the file
> 
> Stream I/O.

Right. For those who might be looking for the same in the future:


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

procedure Test is

   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;
      
      -- 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", "abc");
   
   -- file with "one line and a half":
   Write_String_To_File ("file3.txt",
      "abc" & Ada.Characters.Latin_1.LF & "xyz");
end Test;


The above is, of course, platform-specific in the sense that some compatibility between characters and stream elements is assumed. This works everywhere.

Having fun with platform-specific newline variants is left as an exercise to the reader. ;-)

-- 
Maciej Sobczak * http://www.inspirel.com


^ permalink raw reply	[relevance 3%]

* Did I find mamory leak in Generic Image Decoder (GID) ?
@ 2015-02-02  5:50  2% reinkor
  0 siblings, 0 replies; 200+ results
From: reinkor @ 2015-02-02  5:50 UTC (permalink / raw)


Dear All,

I tried out GID (Generic Image Decoder) from

http://sourceforge.net/projects/gen-img-dec/

The point was to read jpeg-images from my Ada program
"wrapped" in a function:

  function  read_jpg(cfile_jpg : String) return image1.imgc_t;

The source code is below. However, this function seems to eat memory
during (say 200) repeated calls to it (large images, 2000x1800 pixels each).

I did something very very stupid ?

reinert

----------------------------------------------------------------------

Here is the actual code:

with Ada.Streams.Stream_IO;
use Ada.Streams.Stream_IO;

with Ada.Characters.Latin_1;

with Interfaces.C;
with Interfaces.C.Strings;

with system;
with Ada.Unchecked_Conversion;
with Interfaces;

with GID;
with Ada.Calendar;
with Ada.Characters.Handling;           use Ada.Characters.Handling;
with Ada.Text_IO;                       use Ada.Text_IO;
with Ada.Unchecked_Deallocation;

with Text_IO; use Text_IO;




package body file_handling3 is

  package Int_Io is new Text_IO.Integer_Io (Integer);
  use Int_Io;

  use Interfaces;

  type Byte_Array is array(Integer range <>) of Unsigned_8;
  type p_Byte_Array is access Byte_Array;
  procedure Dispose is new Ada.Unchecked_Deallocation(Byte_Array, p_Byte_Array);


  img_buf: p_Byte_Array := null;

  procedure Free_buf is new Ada.Unchecked_Deallocation(Object => Byte_Array, Name => p_Byte_Array);

  procedure Load_raw_image(
    image : in out GID.Image_descriptor;
    buffer: in out p_Byte_Array;
    next_frame: out Ada.Calendar.Day_Duration
  )
  is
    subtype Primary_color_range is Unsigned_8;
    image_width : constant Positive:= GID.Pixel_Width(image);
    image_height: constant Positive:= GID.Pixel_height(image);
    idx: Natural;
    --
    procedure Set_X_Y (x, y: Natural) is
    begin
      idx:= 3 * (x + image_width * (image_height - 1 - y));
    end Set_X_Y;
    --
    procedure Put_Pixel (
      red, green, blue : Primary_color_range;
      alpha            : Primary_color_range
    )
    is
    pragma Warnings(off, alpha); -- alpha is just ignored
    begin
      buffer(idx..idx+2):= (red, green, blue);
      idx:= idx + 3;
      -- ^ GID requires us to look to next pixel on the right for next time.
    end Put_Pixel;

    stars: Natural:= 0;
    procedure Feedback(percents: Natural) is
      so_far: constant Natural:= percents / 5;
    begin
      for i in stars+1..so_far loop
        Put( Standard_Error, '*');
      end loop;
      stars:= so_far;
    end Feedback;

    procedure Load_image is
      new GID.Load_image_contents(
        Primary_color_range, Set_X_Y,
        Put_Pixel, Feedback, GID.fast
      );

  begin
    Dispose(buffer);
    buffer:= new Byte_Array(0..3 * image_width * image_height - 1);
    Load_image(image, next_frame);
  end Load_raw_image;



 function read_jpg(cfile_jpg : String) return image1.imgc_t is
    f: Ada.Streams.Stream_IO.File_Type;
    i: GID.Image_descriptor;
    name : String := cfile_jpg;
    up_name: constant String:= To_Upper(name);
    next_frame, current_frame: Ada.Calendar.Day_Duration:= 0.0;
    isx,isy : Integer;
 begin

    Open(f, In_File, name);
    GID.Load_image_header(
      i,
      Stream(f).all,
      try_tga =>
        name'Length >= 4 and then
        up_name(up_name'Last-3..up_name'Last) = ".TGA"
    );
    Load_raw_image(i, img_buf, next_frame);
    Close(f);
    isx := GID.Pixel_Width(i);
    isy := GID.Pixel_Height(i);
    New_line;
    Put(" isx,isy: ");Put(Integer'Image(isx));Put(Integer'Image(isy));
    New_line;

    declare
      img1 : image1.imgc_t(1..isx,1..isy) := (others => (others => image1.Black));
      Index : Positive;
    begin
      Index := img_buf'First;
      for j in img1'Range (2) loop
          for i in img1'Range (1) loop
              img1(i,isy - j + 1).red   := image1.Short_I(img_buf (Index + 0));
              img1(i,isy - j + 1).green := image1.Short_I(img_buf (Index + 1));
              img1(i,isy - j + 1).blue  := image1.Short_I(img_buf (Index + 2));
              Index := Index + 3;
          end loop;
      end loop;
      Free_buf(img_buf);

      return img1;
    end;
 end read_jpg;

end file_handling3;

^ permalink raw reply	[relevance 2%]

* Re: Ada.Containers warnings with gnat
  2014-11-17  8:13  3%         ` Björn Lundin
@ 2014-11-17 16:39  0%           ` Anh Vo
  0 siblings, 0 replies; 200+ results
From: Anh Vo @ 2014-11-17 16:39 UTC (permalink / raw)


On Monday, November 17, 2014 12:12:05 AM UTC-8, björn lundin wrote:
> On 2014-11-16 18:32, Jeffrey Carter wrote:
> > On 11/16/2014 04:37 AM, Björn Lundin wrote:
> >>
> >> It seems to be ok until I - in the body - do
> >>
> >> with Ada.Streams;
> > 
> > Delete this one and see what happens. It shouldn't change anything since
> > 
> >> with Ada.Streams.Stream_IO;
> > 
> > includes it.
> >  
> Spot on. No warnings anymore.
> Thanks.
> 
> But since the with-clause is in the body,
> one would think that the warnings would refer to the body, not the spec...
> 
> I actually with'ed Ada.Streams for symmetry reason,
> 
> with Ada;
> with Ada.Streams;
> with Ada.Streams.Stream_IO;
> 
> looks better (to me) than just
> 
> with Ada.Streams.Stream_IO;
>  
> It seems that I will need some cognitive training to change my preferences.
 
Yes, you should since it means more with less :-)

Anh Vo.


^ permalink raw reply	[relevance 0%]

* Re: Ada.Containers warnings with gnat
  2014-11-16 17:32  0%       ` Jeffrey Carter
@ 2014-11-17  8:13  3%         ` Björn Lundin
  2014-11-17 16:39  0%           ` Anh Vo
  0 siblings, 1 reply; 200+ results
From: Björn Lundin @ 2014-11-17  8:13 UTC (permalink / raw)


On 2014-11-16 18:32, Jeffrey Carter wrote:
> On 11/16/2014 04:37 AM, Björn Lundin wrote:
>>
>> It seems to be ok until I - in the body - do
>>
>> with Ada.Streams;
> 
> Delete this one and see what happens. It shouldn't change anything since
> 
>> with Ada.Streams.Stream_IO;
> 
> includes it.
> 

Spot on. No warnings anymore.
Thanks.

But since the with-clause is in the body,
one would think that the warnings would refer to the body, not the spec...

I actually with'ed Ada.Streams for symmetry reason,

with Ada;
with Ada.Streams;
with Ada.Streams.Stream_IO;

looks better (to me) than just

with Ada.Streams.Stream_IO;


It seems that I will need some cognitive training to change my preferences.


--
Björn


^ permalink raw reply	[relevance 3%]

* Re: Ada.Containers warnings with gnat
  2014-11-16 11:37  3%     ` Björn Lundin
@ 2014-11-16 17:32  0%       ` Jeffrey Carter
  2014-11-17  8:13  3%         ` Björn Lundin
  0 siblings, 1 reply; 200+ results
From: Jeffrey Carter @ 2014-11-16 17:32 UTC (permalink / raw)


On 11/16/2014 04:37 AM, Björn Lundin wrote:
> 
> It seems to be ok until I - in the body - do
> 
> with Ada.Streams;

Delete this one and see what happens. It shouldn't change anything since

> with Ada.Streams.Stream_IO;

includes it.

-- 
Jeff Carter
"What I wouldn't give for a large sock with horse manure in it."
Annie Hall
42

^ permalink raw reply	[relevance 0%]

* Re: Ada.Containers warnings with gnat
  @ 2014-11-16 11:37  3%     ` Björn Lundin
  2014-11-16 17:32  0%       ` Jeffrey Carter
  0 siblings, 1 reply; 200+ results
From: Björn Lundin @ 2014-11-16 11:37 UTC (permalink / raw)


On 2014-11-16 11:05, Björn Lundin wrote:

It seems to be ok until I - in the body - do

with Ada.Streams;
with Ada.Streams.Stream_IO;

With no code actually using stream_io I get



   21.   package Sample_Map_Pack is new Ada.Containers.Ordered_Maps
          |
        >>> warning: in instantiation at a-coorma.ads:266
        >>> warning: no entities of package "Ada.Streams" are referenced

    27.   package Marketid_Map_Pack is new Ada.Containers.Hashed_Maps
          |
        >>> warning: in instantiation at a-cohama.ads:342
        >>> warning: no entities of package "Ada.Streams" are referenced
        >>> warning: in instantiation at a-chtgop.ads:154
        >>> warning: in instantiation at a-cohama.adb:85
        >>> warning: no entities of package "Ada.Streams" are referenced
        >>> warning: in instantiation at a-chtgop.ads:165
        >>> warning: in instantiation at a-cohama.adb:85
        >>> warning: no entities of package "Ada.Streams" are referenced
        >>> warning: in instantiation at a-chtgop.ads:165
        >>> warning: in instantiation at a-cohama.adb:103
        >>> warning: no entities of package "Ada.Streams" are referenced
        >>> warning: in instantiation at a-chtgop.ads:154
        >>> warning: in instantiation at a-cohama.adb:104
        >>> warning: no entities of package "Ada.Streams" are referenced

    34.   package Winner_Map_Pack is new Ada.Containers.Hashed_Maps
          |
        >>> warning: in instantiation at a-cohama.ads:342
        >>> warning: no entities of package "Ada.Streams" are referenced
        >>> warning: in instantiation at a-chtgop.ads:154
        >>> warning: in instantiation at a-cohama.adb:85
        >>> warning: no entities of package "Ada.Streams" are referenced
        >>> warning: in instantiation at a-chtgop.ads:165
        >>> warning: in instantiation at a-cohama.adb:85
        >>> warning: no entities of package "Ada.Streams" are referenced
        >>> warning: in instantiation at a-chtgop.ads:165
        >>> warning: in instantiation at a-cohama.adb:103
        >>> warning: no entities of package "Ada.Streams" are referenced
        >>> warning: in instantiation at a-chtgop.ads:154
        >>> warning: in instantiation at a-cohama.adb:104
        >>> warning: no entities of package "Ada.Streams" are referenced

    41.   package Win_Place_Map_Pack is new Ada.Containers.Hashed_Maps
          |
        >>> warning: in instantiation at a-cohama.ads:342
        >>> warning: no entities of package "Ada.Streams" are referenced
        >>> warning: in instantiation at a-chtgop.ads:154
        >>> warning: in instantiation at a-cohama.adb:85
        >>> warning: no entities of package "Ada.Streams" are referenced
        >>> warning: in instantiation at a-chtgop.ads:165
        >>> warning: in instantiation at a-cohama.adb:85
        >>> warning: no entities of package "Ada.Streams" are referenced
        >>> warning: in instantiation at a-chtgop.ads:165
        >>> warning: in instantiation at a-cohama.adb:103
        >>> warning: no entities of package "Ada.Streams" are referenced
        >>> warning: in instantiation at a-chtgop.ads:154
        >>> warning: in instantiation at a-cohama.adb:104
        >>> warning: no entities of package "Ada.Streams" are referenced

 763 lines: No errors, 50 warnings



If I then move on to actually use Streams_io, the warnings are reduced to


==============Error messages for source file:
/home/bnl/bnlbot/botstart/bot-1-0/source/ada/local/utils/simulation_storage.ads
    21.   package Sample_Map_Pack is new Ada.Containers.Ordered_Maps
          |
        >>> warning: in instantiation at a-coorma.ads:266
        >>> warning: no entities of package "Ada.Streams" are referenced

    27.   package Marketid_Map_Pack is new Ada.Containers.Hashed_Maps
          |
        >>> warning: in instantiation at a-cohama.ads:342
        >>> warning: no entities of package "Ada.Streams" are referenced

    34.   package Winner_Map_Pack is new Ada.Containers.Hashed_Maps
          |
        >>> warning: in instantiation at a-cohama.ads:342
        >>> warning: no entities of package "Ada.Streams" are referenced

    41.   package Win_Place_Map_Pack is new Ada.Containers.Hashed_Maps
          |
        >>> warning: in instantiation at a-cohama.ads:342
        >>> warning: no entities of package "Ada.Streams" are referenced

 763 lines: No errors, 8 warnings



the actual usage is just

    declare
     File   : Ada.Streams.Stream_IO.File_Type;
     Stream : Ada.Streams.Stream_IO.Stream_Access;
     Filename : String := Global_Map_Files(Marketid).Filename.Fix_String;
    begin
      Ada.Streams.Stream_IO.Open
          (File => File,
           Name => Filename,
           Mode => Ada.Streams.Stream_IO.In_File);
      Stream := Ada.Streams.Stream_IO.Stream (File);
      Marketid_Map_Pack.Map'Read(Stream, Marketid_Map);
      Ada.Streams.Stream_IO.Close(File);
      Log(Object & Service, "Marketid_Map read from file " & Filename);
    end;

for 3 different maps, and 3 corresponding Write sections


however I have put the generic instansiation between
pragma Warnings(Off)
pragma Warnings(On)

but it is still somewhat strange I think




--
Björn


^ permalink raw reply	[relevance 3%]

* Ada.Containers warnings with gnat
@ 2014-11-15 14:35  3% Björn Lundin
    0 siblings, 1 reply; 200+ results
From: Björn Lundin @ 2014-11-15 14:35 UTC (permalink / raw)



Hi!
I'm using a db to keep data in, that I retrieve and
put into ordered and hashed maps from Ada.Containers.

I do this to
 * learn to use Ada standard containers, instead of home-rolled lists
 * to simulate outcome of different parameters into a business modell

Reading from db takes about 1 hour, with i5/ssd/12 gb ram
needless to say, I'd like this to go faster.

So, I rewrote the simulator to use the mentioned containers.
I then run it once, and save the maps into (largish ) files
instead via streams and 'write/'read.

fantastic performance.

The simulator was in a single file before -> no problem.
So I then refactored and created a storage package and suddenly I get
warnings like

 /home/bnl/bnlbot/botstart/bot-1-0/source/ada/local/utils/simulation_storage.ads
    17.   package Sample_Map_Pack is new Ada.Containers.Ordered_Maps
          |
        >>> warning: in instantiation at a-coorma.ads:266
        >>> warning: no entities of package "Ada.Streams" are referenced

    23.   package Marketid_Map_Pack is new Ada.Containers.Hashed_Maps
          |
        >>> warning: in instantiation at a-cohama.ads:342
        >>> warning: no entities of package "Ada.Streams" are referenced

    30.   package Winner_Map_Pack is new Ada.Containers.Hashed_Maps
          |
        >>> warning: in instantiation at a-cohama.ads:342
        >>> warning: no entities of package "Ada.Streams" are referenced

    37.   package Win_Place_Map_Pack is new Ada.Containers.Hashed_Maps
          |
        >>> warning: in instantiation at a-cohama.ads:342
        >>> warning: no entities of package "Ada.Streams" are referenced



what do the mean ?
The body of the package uses streams like

    Log("read Marketid_Map from file ");
    declare
     File   : Ada.Streams.Stream_IO.File_Type;
     Stream : Ada.Streams.Stream_IO.Stream_Access;
     Filename : String := Map_files(Marketid).Filename.Fix_String;
    begin
      Ada.Streams.Stream_IO.Open
          (File => File,
           Name => Filename,
           Mode => Ada.Streams.Stream_IO.In_File);
      Stream := Ada.Streams.Stream_IO.Stream (File);
      Marketid_Map_Pack.Map'Read(Stream, Marketid_Map);
      Ada.Streams.Stream_IO.Close(File);
      Log("Marketid_Map read from file " & Filename);
    end;




package spec is

---------------------------
with Ada;
with Ada.Strings;
with Ada.Strings.Hash;

with Ada.Containers;
with Ada.Containers.Hashed_Maps;
with Ada.Containers.Ordered_Maps;

with Calendar2;
with Bot_Types; use Bot_Types;
with Table_Apricesfinish;
with Table_Arunners;

package Simulation_Storage is

  package Sample_Map_Pack is new Ada.Containers.Ordered_Maps
        (Key_Type     => Calendar2.Time_Type,
         Element_Type => Table_Apricesfinish.Apricesfinish_List_Pack2.List,
         "<"          => Calendar2."<",
         "="          => Table_Apricesfinish.Apricesfinish_List_Pack2."=");

  package Marketid_Map_Pack is new Ada.Containers.Hashed_Maps
        (Market_Id_Type,
         Sample_Map_Pack.Map,
         Ada.Strings.Hash,
         "=",
         Sample_Map_Pack."=");

  package Winner_Map_Pack is new Ada.Containers.Hashed_Maps
        (Market_Id_Type,
         Table_Arunners.Arunners_List_Pack2.List,
         Ada.Strings.Hash,
         "=",
         Table_Arunners.Arunners_List_Pack2."=");

  package Win_Place_Map_Pack is new Ada.Containers.Hashed_Maps
        (Market_Id_Type,
         Market_Id_Type,
         Ada.Strings.Hash,
         "=",
         "=");


  procedure Create_Files_From_Database;
  procedure Fill_Maps(Marketid_Map  : out Marketid_Map_Pack.Map;
                      Winner_Map    : out Winner_Map_Pack.Map;
                      Win_Place_Map : out Win_Place_Map_Pack.Map) ;


end Simulation_Storage;



--
Björn

^ permalink raw reply	[relevance 3%]

* Re: Will Ada-95 Programs Written in MS Windows Run in MacOS and Linux Without Some Tweaking.
  @ 2013-12-11  0:34  2%             ` Simon Wright
  0 siblings, 0 replies; 200+ results
From: Simon Wright @ 2013-12-11  0:34 UTC (permalink / raw)


"Randy Brukardt" <randy@rrsoftware.com> writes:

> "Simon Wright" <simon@pushface.org> wrote in message 
> news:lywqjf45za.fsf@pushface.org...
> ...
>> I'm not sure of the best way to get an Ada program not to care what
>> sort of input line terminators it's reading.
>
> I'm surprised that that would be a problem, at least for Unix and
> Windows files. It's pretty simple to design Text_IO so that it can
> read either properly; that's how Text_IO in Janus/Ada works. (The only
> difference for it between Windows and Unix versions is the characters
> output by New_Line).

GNAT is certainly not as clever as that. On Mac OS X, this program

========================================================================
with Ada.Streams.Stream_IO;
with Ada.Integer_Text_IO;
with Ada.Text_IO; use Ada.Text_IO;

procedure S is

   Data_File_Name : constant String := "s.dat";
   Text_File : Ada.Text_IO.File_Type;

   procedure Write_As_Stream (Data : String) is
      package ASS renames Ada.Streams.Stream_IO;
      Stream_File : ASS.File_Type;
   begin
      ASS.Open (Stream_File,
                Name => Data_File_Name,
                Mode => ASS.Out_File);
      declare
         Stream_Access : constant ASS.Stream_Access
           := ASS.Stream (Stream_File); -- the file has to be open already
      begin
         String'Write (Stream_Access, Data);
      end;
      ASS.Close (Stream_File);
   end Write_As_Stream;

begin

   Put_Line ("testing \n");
   Write_As_Stream (String'(1 => ASCII.LF));
   Open (Text_File, Name => Data_File_Name, Mode => In_File);
   Put_Line ("EOL is " & Boolean'Image (End_Of_Line (Text_File)));
   Put_Line ("EOF is " & Boolean'Image (End_Of_File (Text_File)));
   Close (Text_File);

   Put_Line ("testing \r\n");
   Write_As_Stream (String'(1 => ASCII.CR, 2 => ASCII.LF));
   Open (Text_File, Name => Data_File_Name, Mode => In_File);
   Put_Line ("EOL is " & Boolean'Image (End_Of_Line (Text_File)));
   Put_Line ("EOF is " & Boolean'Image (End_Of_File (Text_File)));
   Close (Text_File);

   declare
      Dummy : Integer;
   begin
      Put_Line ("testing \n42");
      Write_As_Stream (String'(1 => ASCII.LF) & "42");
      Open (Text_File, Name => Data_File_Name, Mode => In_File);
      Ada.Integer_Text_IO.Get (Text_File, Dummy);
      Put_Line ("Value is " & Integer'Image (Dummy));
      Close (Text_File);
   end;

   declare
      Dummy : Integer;
   begin
      Put_Line ("testing \r\n42");
      Write_As_Stream (String'(1 => ASCII.CR, 2 => ASCII.LF) & "42");
      Open (Text_File, Name => Data_File_Name, Mode => In_File);
      Ada.Integer_Text_IO.Get (Text_File, Dummy);
      Put_Line ("Value is " & Integer'Image (Dummy));
      Close (Text_File);
   end;

end S;
========================================================================

results in

------------------------------------------------------------------------
testing \n
EOL is TRUE
EOF is TRUE
testing \r\n
EOL is FALSE
EOF is FALSE
testing \n42
Value is  42
testing \r\n42

Execution terminated by unhandled exception
Exception name: ADA.IO_EXCEPTIONS.DATA_ERROR
------------------------------------------------------------------------

whereas on a Windows machine I get

------------------------------------------------------------------------
testing \n
EOL is TRUE
EOF is TRUE
testing \r\n
EOL is TRUE
EOF is TRUE
testing \n42
Value is  42
testing \r\n42
Value is  42
------------------------------------------------------------------------

so I feel a bug report coming on .. 

> But if you don't want to change the terminators (or your compiler has an 
> unnecessarily inflexible Text_IO), I'd suggest using Stream_IO. Of course, 
> then you'll have to do your own buffering of input (but that's usually a 
> good idea anyway).

Yes. Actually I tried Sequential_IO, but for just reading Characters
there's not a lot of difference ... is there?


^ permalink raw reply	[relevance 2%]

* Re: Calling a File for Encryption from outside of the Main Ada-95 Holding Folder.
  2013-09-05 11:33  1%             ` Simon Wright
  2013-09-05 15:46  0%               ` Austin Obyrne
@ 2013-09-05 16:00  0%               ` Austin Obyrne
  1 sibling, 0 replies; 200+ results
From: Austin Obyrne @ 2013-09-05 16:00 UTC (permalink / raw)


On Thursday, September 5, 2013 12:33:32 PM UTC+1, Simon Wright wrote:
> Austin Obyrne <austin.obyrne@hotmail.com> writes: > I have tried Word Pad also and iit works equally well - but as you say > the file extension .doc is taboo - must not be used - .dat is fine It's not the file extension, it's the contents of the file! (I realise that many people would have trouble making the distinction). > Summarising. > > Users can use 'Notepad' with .dat file extension say > Users can use 'Wordpad' with .dat file extension It would be more normal to use .txt > If users insist on using MS Word then it must go through the AdaGIDE > editor with a .dat file extension (if any). Or Notepad, or Wordpad .. what you are doing is Copying the contents of the Word document, and Pasting them into an editor which doesn't understand Word's style and format information and only accepts the raw characters. Which is all that you are interested in. I don't think it's entirely reasonable from your users' point of view to only be able to deal with plain text files, though; for example, what about images? (.jpg, etc) which are going to give you the same problem. Perhaps you could consider reading the files using Ada.Streams.Stream_IO? Example use in procedure Output_Contents starting at line 182 of http://goo.gl/wcqkop

Could I take (.txt) for everything as standard in future and not bother with (.dat) even - I would like to be able to imply this as a caveat to my users - what do you say O' Wise One?

AdaGIDE will always accept .txt ???

I would like to use just one rule.

You guys have really sorted things for me - I am truly grateful for your help.

Knowing about the file extensons drop down menu options menu is just marvellous.

Grateful to everybody.

Austin

^ permalink raw reply	[relevance 0%]

* Re: Calling a File for Encryption from outside of the Main Ada-95 Holding Folder.
  2013-09-05 11:33  1%             ` Simon Wright
@ 2013-09-05 15:46  0%               ` Austin Obyrne
  2013-09-05 16:00  0%               ` Austin Obyrne
  1 sibling, 0 replies; 200+ results
From: Austin Obyrne @ 2013-09-05 15:46 UTC (permalink / raw)


On Thursday, September 5, 2013 12:33:32 PM UTC+1, Simon Wright wrote:
> Austin Obyrne <austin.obyrne@hotmail.com> writes: > I have tried Word Pad also and iit works equally well - but as you say > the file extension .doc is taboo - must not be used - .dat is fine It's not the file extension, it's the contents of the file! (I realise that many people would have trouble making the distinction). > Summarising. > > Users can use 'Notepad' with .dat file extension say > Users can use 'Wordpad' with .dat file extension It would be more normal to use .txt > If users insist on using MS Word then it must go through the AdaGIDE > editor with a .dat file extension (if any). Or Notepad, or Wordpad .. what you are doing is Copying the contents of the Word document, and Pasting them into an editor which doesn't understand Word's style and format information and only accepts the raw characters. Which is all that you are interested in. I don't think it's entirely reasonable from your users' point of view to only be able to deal with plain text files, though; for example, what about images? (.jpg, etc) which are going to give you the same problem. Perhaps you could consider reading the files using Ada.Streams.Stream_IO? Example use in procedure Output_Contents starting at line 182 of http://goo.gl/wcqkop

Many thanks Simon,

I think I will leave images for the present - just security of information will be all for now - frankly I dont know enough about images yet but anything that can be reduced to an alpahnumeric can be encrypted by my cipher.

Can I come back to you sometime in the future on this one.

Regards - Austinn

^ permalink raw reply	[relevance 0%]

* Re: Calling a File for Encryption from outside of the Main Ada-95 Holding Folder.
  @ 2013-09-05 11:33  1%             ` Simon Wright
  2013-09-05 15:46  0%               ` Austin Obyrne
  2013-09-05 16:00  0%               ` Austin Obyrne
  0 siblings, 2 replies; 200+ results
From: Simon Wright @ 2013-09-05 11:33 UTC (permalink / raw)


Austin Obyrne <austin.obyrne@hotmail.com> writes:

> I have tried Word Pad also and iit works equally well - but as you say
> the file extension .doc is taboo - must not be used - .dat is fine

It's not the file extension, it's the contents of the file! (I realise
that many people would have trouble making the distinction).

> Summarising.
>
> Users can use 'Notepad' with .dat file extension say
> Users can use 'Wordpad' with .dat file extension

It would be more normal to use .txt

> If users insist on using MS Word then it must go through the AdaGIDE
> editor with a .dat file extension (if any).

Or Notepad, or Wordpad .. what you are doing is Copying the contents of
the Word document, and Pasting them into an editor which doesn't
understand Word's style and format information and only accepts the raw
characters. Which is all that you are interested in.

I don't think it's entirely reasonable from your users' point of view to
only be able to deal with plain text files, though; for example, what
about images? (.jpg, etc) which are going to give you the same
problem. Perhaps you could consider reading the files using
Ada.Streams.Stream_IO?

Example use in procedure Output_Contents starting at line 182 of
http://goo.gl/wcqkop


^ permalink raw reply	[relevance 1%]

* Re: xor
  2012-03-25 19:26  1%     ` xor Niklas Holsti
@ 2012-03-27 20:09  0%       ` Michael Moeller
  0 siblings, 0 replies; 200+ results
From: Michael Moeller @ 2012-03-27 20:09 UTC (permalink / raw)




On Sun, 25 Mar 2012, Niklas Holsti wrote:

> On 12-03-25 18:16 , Michael Moeller wrote:
>> Thank you for your quick answer.
>> 
>> Can I use Unsigned_Byte_T to read in a byte from a file
>> as in C? I haven't looked into this yet.
>
> C has several ways to "read in a byte from a file", depending on the type of 
> the file and how you specify which byte you want to read. Can you be more 
> specific?

I have to read in what in C is called an unsigned byte, which in fact is
a stream of bytes without any interpretation as a symbol. Just a number
from 0 to 255.

In addition it would be nice to call something like 'fstat' to get the 
size of file in advance instead of checking every byte for EOF.

>
> If you mean reading an 8-bit octet from a "binary file" -- that is, not a 
> text file -- you can use the Ada library packages Ada.Sequential_IO or 
> Ada.Direct_IO, depending on your needs. These are generic packages, so you 
> must instantiate them for the type of data, for example Unsigned_Byte_T.
>
> If the file contains a mixture of different kinds of "binary" data, for 
> example both 8-bit data and 16-bit data, or more complex structures, you 
> should use the Ada "stream" facility from Ada.Streams.Stream_IO. The stream 
> facility helps you handle things like different endianness, padding, packing, 
> unusual encodings, and so on.
>
> The stream facility does not use generics; instead, it uses a combination of 
> tagged types and the special "stream attribute" operations T'Read, T'Write, 
> et cetera, which you can define differently for each type, T, that is present 
> in your file. For example, your 'Read operation for a 16-bit integer will 
> specify whether the integer is stored in little-endian or big-endian order in 
> the file (by reading two 8-bit integers, using 'Read for the 8-bit type, in 
> the corresponding order).
>
> The stream technique takes a bit of study to understand, but it works very 
> well, especially if the file has a mixture of different complex structures of 
> data, or if the file is created by a different language or computer and is 
> not in the "native" form for your Ada compiler.
>
> -- 
> Niklas Holsti
> Tidorum Ltd
> niklas holsti tidorum fi
>      .      @       .
>
Perhaps it will be more save to leave the C-procedures alone and to
call them from within Ada instead. I don't know whether this will be 
easier. However, I'll give Sequential_IO and Direct_IO a try.

Regards,
Michael




^ permalink raw reply	[relevance 0%]

* Re: xor
  @ 2012-03-25 19:26  1%     ` Niklas Holsti
  2012-03-27 20:09  0%       ` xor Michael Moeller
  0 siblings, 1 reply; 200+ results
From: Niklas Holsti @ 2012-03-25 19:26 UTC (permalink / raw)


On 12-03-25 18:16 , Michael Moeller wrote:
> Thank you for your quick answer.
>
> Can I use Unsigned_Byte_T to read in a byte from a file
> as in C? I haven't looked into this yet.

C has several ways to "read in a byte from a file", depending on the 
type of the file and how you specify which byte you want to read. Can 
you be more specific?

If you mean reading an 8-bit octet from a "binary file" -- that is, not 
a text file -- you can use the Ada library packages Ada.Sequential_IO or 
Ada.Direct_IO, depending on your needs. These are generic packages, so 
you must instantiate them for the type of data, for example Unsigned_Byte_T.

If the file contains a mixture of different kinds of "binary" data, for 
example both 8-bit data and 16-bit data, or more complex structures, you 
should use the Ada "stream" facility from Ada.Streams.Stream_IO. The 
stream facility helps you handle things like different endianness, 
padding, packing, unusual encodings, and so on.

The stream facility does not use generics; instead, it uses a 
combination of tagged types and the special "stream attribute" 
operations T'Read, T'Write, et cetera, which you can define differently 
for each type, T, that is present in your file. For example, your 'Read 
operation for a 16-bit integer will specify whether the integer is 
stored in little-endian or big-endian order in the file (by reading two 
8-bit integers, using 'Read for the 8-bit type, in the corresponding order).

The stream technique takes a bit of study to understand, but it works 
very well, especially if the file has a mixture of different complex 
structures of data, or if the file is created by a different language or 
computer and is not in the "native" form for your Ada compiler.

-- 
Niklas Holsti
Tidorum Ltd
niklas holsti tidorum fi
       .      @       .



^ permalink raw reply	[relevance 1%]

* Re: Writing Data to a file
  @ 2011-12-15 18:32  3% ` Ludovic Brenta
  0 siblings, 0 replies; 200+ results
From: Ludovic Brenta @ 2011-12-15 18:32 UTC (permalink / raw)


awdorrin <awdorrin@gmail.com> writes:
> I have code that imports the unix 'write' function in order to write a
> stream of byte data.
>
> I had thought that replacing this call with the POSIX.IO.Write would
> make more sense, so that I was using more of a standard method.
>
> Unfortunately, I cannot access the write function within POSIX.IO, so
> I'm stuck with using the Write procedures.
>
> I have the following code, but I'm not sure that I'm doing this the
> right way...
>
> declare
>   Buf_Last : Stream_Element_Count;
>   Buf_Addr : System.Address := AREA_PTR + Storage_Offset(READ_OFFSET);
>   Buf : Stream_Element_Array( 1 .. Stream_Element_Count( WRITE_OFFSET
> - READ_OFFSET) );
>   for Buf'Address use Buf_Addr;
> begin
>   POSIX.IO.Write( File=>FileHandle, Buffer=>Buf, Last=>Buf_Last);
> end;
>
> The original code, using the imported function was:
>
> C_WRITE( File => FileHandle, Buffer=> (Q_AREA_PTR +
> Storage_Offset(READ_OFFSET), Num_Bytes=> (WRITE_OFFSET -
> READ_OFFSET));
>
> having to use the declare section to overlay the Stream_Element_Array
> onto the memory segment of the buffer seems much more complicated; so
> I feel like there is likely an easier way to do this, using standard
> Ada, and not having to import the C write function.
>
> Anyone have any suggestions?

with Ada.Streams.Stream_IO;

declare
   File : Ada.Streams.Stream_IO.File_Type;
   Stream : Ada.Streams.Stream_IO.Stream_Access;
begin
   Ada.Streams.Stream_IO.Open (File => File,
                               Mode => Ada.Streams.Stream_IO.Out_File,
                               Name => "my_output.bin");
   Stream := Ada.Streams.Stream_IO.Stream (File);
   Ada.Streams.Write (Stream => Stream,
                      Item => Buf (1 .. Write_Offset - Read_Offset));
end;

See ARM A.12.1 and 13.13.

The problem you may (or may not) face is converting a POSIX file
descriptor (File_Handle) to a Ada.Streams.Stream_IO.File_Type.  If you
know the name of the file, then the problem disappears, as above.

Note that you have not specified what it is that Buf is supposed to
contain; you seem to assume that an explicit conversion to
Stream_Element_Array is necessary.  It is not; given a stream you might
as well use the stream-oriented attributes (ARM 13.13.2):

package Data is
   type T is private;
private
   -- omitted
end Data;

with Ada.Streams.Stream_IO;
with Data;

declare
   -- as above
   Item : Data.T;
begin
   Data.T'Output (Stream, Item);  -- emits bounds and discriminants
   Data.T'Write (Stream, Item); -- does not emit bounds or discriminants
end;

-- 
Ludovic Brenta.



^ permalink raw reply	[relevance 3%]

* Re: Address and bit mask
  @ 2011-08-31  8:35  3%           ` Ludovic Brenta
  0 siblings, 0 replies; 200+ results
From: Ludovic Brenta @ 2011-08-31  8:35 UTC (permalink / raw)


milouz wrote:
> On Aug 30, 5:14 pm, Adam Beneschan <a...@irvine.com> wrote:
>
>> If the reason you want to do address arithmetic is something else,
>> though, you're welcome to ask about it, but rather than giving us C
>> code with no context and asking us how to translate it, please give us
>> a bigger-picture description of what you're trying to accomplish
>
> Ok, so I'll try to be more precise.
> I have to parse a list of chunks which are 4 bytes aligned. Each chunk
> is like this:
>
>   [ size |    data     ]
>
> The 'size' field is a 32-bit unsigned integer and it's the size of the
> whole chunk.
> The 'data' field has various lenght (>= 1 byte).
>
> I can solve that problem in a C-ish style, but I wonder what is the
> proper way to solve that problem in Ada.

If the chunks are contiguous in memory (or, better yet, in a file), my
first reaction would be to construct a stream and then use
Interfaces.Unsigned_32'Read to read the sizes and
Interfaces.Unsigned_X'Read to read the data.  Something like:

with Ada.Streams.Stream_IO;
with Interfaces;

procedure Parse (File_Name : in String) is
   File : Ada.Streams.Stream_IO.File_Type;
begin
   Ada.Streams.Stream_IO.Open (File => File,
                               Mode => Ada.Streams.Stream_IO.In_Mode,
                               Name => File_Name);
   Parse (Ada.Streams.Stream_IO.Stream (File));
end Parse;

procedure Parse (Stream : in Ada.Streams.Stream_IO.Stream_Access) is
   Length : Interfaces.Unsigned_32;
   Alignment : constant := 4;
   Padding_Byte : Interfaces.Unsigned_8;
begin
   Interfaces.Unsigned_32'Read (Stream, Length);
   declare
      Data : Ada.Streams.Stream_Element_Array
               (1 .. Ada.Streams.Stream_Element_Count (Length));
      Last : Ada.Streams.Stream_Element_Offset;
   begin
      Ada.Streams.Read (Stream, Data, Last);
      if Last < Length then
         raise Program_Error with "not enough data in the stream";
      end if;
      -- process Data here
   end;
   -- Now read as many padding bytes as necessary to reach the next
alignment
   -- boundary
   if Length mod Alignment /= 0 then
      for J in 1 .. Alignment - Length mod Alignment loop
         Interfaces.Unsigned_8'Read (Stream, Padding_Byte);
      end loop;
   end if;
end Parse;

--
Ludovic Brenta.
The Chief Legal Officer globally achieves the industry-standard
baseline starting point.



^ permalink raw reply	[relevance 3%]

* Re: Why no socket package in the standard ?
  @ 2011-05-25 15:12 14%   ` Tero Koskinen
  0 siblings, 0 replies; 200+ results
From: Tero Koskinen @ 2011-05-25 15:12 UTC (permalink / raw)


Hi,

On Tue, 24 May 2011 06:11:43 +0000 (UTC) tmoran@acm.org wrote:

> > Except (I just looked at the source) I personally don't enjoy bindings
> > which end to introduce C like namings [*] in Ada. Things like PF_INET,
> > IPPROTO_IP or SOL_SOCKET looks really strange for an Ada source;
> 
> A thicker binding is NC sockets ("Not Claw", derived from Claw.Sockets).
> It's nc.zip at www.adaworld.com, look there under
> Ada Projects/Ada Internet Projects/Internet Protocols
> It's for Windows but IIRC the WSAStartup and WSACleanup should be
> the only Windows specific things.

Here is a diff which allows the package to compile on OpenBSD/amd64.
(It includes also some filename upper/lower case corrections, so
 the diff is pretty big.)

The example programs still segfault. I guess the datastructure
definitions are incorrect.

diff -r f734a2862510 -r 2cca25a3f5f4 GETJPG.ADB
--- a/GETJPG.ADB	Tue Dec 21 19:45:44 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,75 +0,0 @@
--- Sample program using NC.Sockets
--- It goes to the San Jose State weathercam and downloads to pic.jpg
--- a picture of the current skyline in San Jose, California
--- Copyright 2003 tmoran@acm.org anyone may use for any purpose
-with Ada.Streams,
-     Ada.Streams.Stream_IO,
-     Ada.Text_IO,
-     Nc.Sockets;
-procedure Getjpg is
-  use type Ada.Streams.Stream_Element_Offset;
-
-  Buffer  : Ada.Streams.Stream_Element_Array(1 .. 5000);
-  Last    : Ada.Streams.Stream_Element_Offset;
-  F       : Ada.Streams.Stream_IO.File_Type;
-  Socket  : Nc.Sockets.Socket_Type;
-  Length  : Ada.Streams.Stream_Element_Offset := 0;
-  type States is (Start, Seen_CR1, Seen_LF1, Seen_CR2, In_Data);
-  subtype Header is States range Start .. Seen_Cr2;
-  State   : States := Start;
-
-  procedure Write is
-    use Ada.Streams;
-    C : Character;
-    Watch_For : constant array(Header) of Character
-      := (Start => Ascii.CR, Seen_CR1 => Ascii.LF, Seen_LF1 => Ascii.CR,
-          Seen_CR2 => Ascii.LF);
-  begin
-    if State = In_Data then
-      Stream_IO.Write(F, Buffer(1 .. Last));
-      Length := Length + Last;
-      return;
-    end if;
-    for I in 1 .. Last loop
-      C := Character'Val(Stream_Element'Pos(Buffer(I)));
-      Ada.Text_IO.Put(C);
-      if C = Watch_For(State) then
-        State := States'succ(State);
-        if State = In_Data then
-          Stream_Io.Create(F, Stream_Io.Out_File, "pic.jpg");
-          if I < Last then
-            Stream_Io.Write(F, Buffer(I + 1 .. Last));
-            Length := Last - I;
-          end if;
-          exit;
-        end if;
-      else
-        State := Start;
-      end if;
-    end loop;
-  end Write;
-
-  procedure Stop is
-  begin
-    Ada.Text_IO.Put_Line(Ada.Streams.Stream_Element_Offset'Image(Length)
-                         & " file pic.jpg written");
-    if Ada.Streams.Stream_IO.Is_Open(F) then
-      Ada.Streams.Stream_IO.Close(F);
-    end if;
-  end Stop;
-
-begin
-  Nc.Sockets.Open(Socket, "metsun1.met.sjsu.edu", 80, Timeout => 20.0);
-  Nc.Sockets.Put_Line(Socket, "GET /cam_directory/latest.jpg HTTP/1.0");
-  Nc.Sockets.Put_Line(Socket, "");
-  loop
-    Nc.Sockets.Input(Socket, Timeout => 10.0, Item => Buffer, Last => Last);
-    exit when Last < Buffer'First;
-    Write;
-  end loop;
-  Nc.Sockets.Close(Socket);
-  Stop;
-exception
-  when Nc.Not_Found_Error =>
-    Stop;
-end Getjpg;
diff -r f734a2862510 -r 2cca25a3f5f4 NC.ADS
--- a/NC.ADS	Tue Dec 21 19:45:44 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,19 +0,0 @@
-with Interfaces.C;
-package NC is
-  type Short is new Interfaces.C.Short;
-  type Int is new Interfaces.C.Int;
-  subtype Natural_Int is Int range 0 .. Int'last;
-  type UInt is new Interfaces.C.Unsigned;
-  type DWord is new Interfaces.C.Unsigned_Long;
-
-  type Byte is range 0 .. 255;
-  for Byte'size use 8;
-  type Word is mod 2**16;
-  for Word'size use 16;
-
-  Windows_Error,
-  Not_Valid_Error,
-  Already_Valid_Error,
-  Not_Found_Error : Exception;
-  type Lpcstr is access all Interfaces.C.Char;
-end NC;
diff -r f734a2862510 -r 2cca25a3f5f4 getjpg.adb
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/getjpg.adb	Wed Dec 22 18:05:52 2010 +0200
@@ -0,0 +1,75 @@
+-- Sample program using NC.Sockets
+-- It goes to the San Jose State weathercam and downloads to pic.jpg
+-- a picture of the current skyline in San Jose, California
+-- Copyright 2003 tmoran@acm.org anyone may use for any purpose
+with Ada.Streams,
+     Ada.Streams.Stream_IO,
+     Ada.Text_IO,
+     Nc.Sockets;
+procedure Getjpg is
+  use type Ada.Streams.Stream_Element_Offset;
+
+  Buffer  : Ada.Streams.Stream_Element_Array(1 .. 5000);
+  Last    : Ada.Streams.Stream_Element_Offset;
+  F       : Ada.Streams.Stream_IO.File_Type;
+  Socket  : Nc.Sockets.Socket_Type;
+  Length  : Ada.Streams.Stream_Element_Offset := 0;
+  type States is (Start, Seen_CR1, Seen_LF1, Seen_CR2, In_Data);
+  subtype Header is States range Start .. Seen_Cr2;
+  State   : States := Start;
+
+  procedure Write is
+    use Ada.Streams;
+    C : Character;
+    Watch_For : constant array(Header) of Character
+      := (Start => Ascii.CR, Seen_CR1 => Ascii.LF, Seen_LF1 => Ascii.CR,
+          Seen_CR2 => Ascii.LF);
+  begin
+    if State = In_Data then
+      Stream_IO.Write(F, Buffer(1 .. Last));
+      Length := Length + Last;
+      return;
+    end if;
+    for I in 1 .. Last loop
+      C := Character'Val(Stream_Element'Pos(Buffer(I)));
+      Ada.Text_IO.Put(C);
+      if C = Watch_For(State) then
+        State := States'succ(State);
+        if State = In_Data then
+          Stream_Io.Create(F, Stream_Io.Out_File, "pic.jpg");
+          if I < Last then
+            Stream_Io.Write(F, Buffer(I + 1 .. Last));
+            Length := Last - I;
+          end if;
+          exit;
+        end if;
+      else
+        State := Start;
+      end if;
+    end loop;
+  end Write;
+
+  procedure Stop is
+  begin
+    Ada.Text_IO.Put_Line(Ada.Streams.Stream_Element_Offset'Image(Length)
+                         & " file pic.jpg written");
+    if Ada.Streams.Stream_IO.Is_Open(F) then
+      Ada.Streams.Stream_IO.Close(F);
+    end if;
+  end Stop;
+
+begin
+  Nc.Sockets.Open(Socket, "metsun1.met.sjsu.edu", 80, Timeout => 20.0);
+  Nc.Sockets.Put_Line(Socket, "GET /cam_directory/latest.jpg HTTP/1.0");
+  Nc.Sockets.Put_Line(Socket, "");
+  loop
+    Nc.Sockets.Input(Socket, Timeout => 10.0, Item => Buffer, Last => Last);
+    exit when Last < Buffer'First;
+    Write;
+  end loop;
+  Nc.Sockets.Close(Socket);
+  Stop;
+exception
+  when Nc.Not_Found_Error =>
+    Stop;
+end Getjpg;
diff -r f734a2862510 -r 2cca25a3f5f4 nc-sockets-alt_gethostbyname.adb
--- a/nc-sockets-alt_gethostbyname.adb	Tue Dec 21 19:45:44 2010 +0200
+++ b/nc-sockets-alt_gethostbyname.adb	Wed Dec 22 18:05:52 2010 +0200
@@ -10,7 +10,7 @@
     end loop;
     Result.P_Hostent := NC.Sockets.B_Helper.gethostbyname(Result.C_Name(0)'unchecked_access);
     if Result.P_Hostent = null then
-      Result.Error := NC.Sockets.B_Helper.WSAGetLastError;
+      Result.Error := 0;
     end if;
     Result.Output_Ready:=True;
     while not Result.Fini loop
diff -r f734a2862510 -r 2cca25a3f5f4 nc-sockets.adb
--- a/nc-sockets.adb	Tue Dec 21 19:45:44 2010 +0200
+++ b/nc-sockets.adb	Wed Dec 22 18:05:52 2010 +0200
@@ -32,6 +32,10 @@
   use Claw.Sockets.Low_Level;
 
   System_Control : System_Controls;
+  function WSAGetLastError return Error_Codes is
+  begin
+     return 0;
+  end WSAGetLastError;
 
   procedure Get_Error_Code(Info       : in out Host_Info_Type;
                            Error_Code :    out Error_Codes) is
@@ -212,8 +216,10 @@
 
       C_Name_Length : Size_T := Claw.sockets.Alt_Gethostbyname.C_Name_Type'length;
 
-      function Get_Last_Error return Claw.DWord;
-      pragma Import (StdCall, Get_Last_Error, "GetLastError");
+      function Get_Last_Error return Claw.DWord is
+      begin
+         return 0;
+      end Get_Last_Error;
 
     begin
 
@@ -489,19 +495,13 @@
       if Is_Running then
         Error := 0;
       else
-        Error := WSAStartup(16#0101#, wsadata'access);
-        if Error = 0 then
-          Is_Running := True;
-        end if;
+        Is_Running := True;
       end if;
     end Make_Running;
 
     procedure Make_Stopped is
     begin
       if not Is_Running then return;end if;
-      if WSACleanup = Socket_Error then
-        raise Claw.windows_error;  -- to be caught by Shut_Down
-      end if;
       Is_Running := False;
     end Make_Stopped;
   end Winsock_Systems;
diff -r f734a2862510 -r 2cca25a3f5f4 nc-sockets.ads
--- a/nc-sockets.ads	Tue Dec 21 19:45:44 2010 +0200
+++ b/nc-sockets.ads	Wed Dec 22 18:05:52 2010 +0200
@@ -8,7 +8,7 @@
 
 package NC.Sockets is
   package Claw renames NC;
-  pragma Link_With("libwsock32.a");
+  -- pragma Link_With("libwsock32.a");
     --
     -- Edit History:
     --
@@ -746,13 +746,13 @@
       Host_Address_List_Ptr : Host_Address_List_Ptr_Type; -- h_addr_list
   end record;
   for Hostents use record
-      Host_Name_Ptr at 0 range 0 .. 31;
-      Host_Alias_Ptr_List at 4 range 0 .. 31;
-      Host_Address_Kind at 8 range 0 .. 15;
-      Host_Address_Length at 10 range 0 .. 15;
-      Host_Address_List_Ptr at 12 range 0 .. 31;
+      Host_Name_Ptr at 0 range 0 .. 63;
+      Host_Alias_Ptr_List at 8 range 0 .. 63;
+      Host_Address_Kind at 16 range 0 .. 15;
+      Host_Address_Length at 18 range 0 .. 15;
+      Host_Address_List_Ptr at 20 range 0 .. 63;
   end record;
-  for Hostents'size use 16*8;
+  for Hostents'size use 224;
 
   type Hostent_Ptr_Type is access all HOSTENTs;
 
@@ -782,9 +782,9 @@
     Last_Error_Code : Error_Codes := 0;
   end record;
   for W_Host_Info_Type use record
-    Hostent at 0 range 0 .. 16*8-1;
-    Data_Area at 16 range 0 .. (MAXGETHOSTSTRUCT-16)*8-1;
-    Last_Error_Code at MAXGETHOSTSTRUCT range 0 .. 31;
+    Hostent at 0 range 0 .. 224-1;
+    Data_Area at 32 range 0 .. (MAXGETHOSTSTRUCT-16)*8-1;
+    Last_Error_Code at (MAXGETHOSTSTRUCT+32) range 0 .. 31;
   end record;
 
   procedure Copy_Host_Info(Source : in W_Host_Info_Type;
@@ -800,16 +800,15 @@
   package Low_Level is
     use type Claw.Int;
 
-    function WSAGetLastError return Error_Codes;
-    pragma Import(Stdcall, WSAGetLastError, "WSAGetLastError");
+    -- function WSAGetLastError return Error_Codes;
 
     function gethostbyname(name: NC.lpcstr) return Hostent_Ptr_Type;
-    pragma Import(Stdcall, gethostbyname, "gethostbyname");
+    pragma Import(C, gethostbyname, "gethostbyname");
 
     function gethostbyaddr(addr: access Network_Address_Type;
                            len : Claw.Int := Network_Address_Type'size/8;
                            kind : Claw.Int := PF_Inet) return Hostent_Ptr_Type;
-    pragma Import(Stdcall, gethostbyaddr, "gethostbyaddr");
+    pragma Import(C, gethostbyaddr, "gethostbyaddr");
 
     WSADescription_Len : constant := 256;
     WSASys_Status_Len  : constant := 128;
@@ -829,21 +828,13 @@
         szSystemStatus at 261 range 0 .. 129*8-1;
         iMaxSockets    at 390 range 0 .. 15;
         iMaxUdpDg      at 392 range 0 .. 15;
-        lpVendorInfo   at 394 range 0 .. 31;
+        lpVendorInfo   at 394 range 0 .. 63;
     end record;
-    for WSADatas'size use 398*8;
-
-    function WSAStartup (wVersionRequired : NC.word;
-                         lpWSAData      : access WSADatas)
-             return Error_Codes;
-    pragma Import(Stdcall, WSAStartup, "WSAStartup");
-
-    function WSACleanup return Claw.Int;
-    pragma Import(Stdcall, WSACleanup, "WSACleanup");
+    for WSADatas'size use 3216;
 
     function gethostname(Name : NC.lpcstr;
                          Length : Claw.Int) return Claw.Int;
-    pragma Import(Stdcall, gethostname, "gethostname");
+    pragma Import(C, gethostname, "gethostname");
 
     type Address_Family_Type is new Claw.short;
     AF_INET : constant Address_Family_Type := 2;
@@ -851,7 +842,7 @@
     type Network_Port_Type is new NC.word; -- network byte order
 
     function htons(hostshort: Port_Type) return Network_Port_Type;
-    pragma Import(Stdcall, htons, "htons");
+    pragma Import(C, htons, "htons");
 
     type SOCKADDR_INs is record
       Family  : Address_Family_Type := AF_INET;
@@ -863,32 +854,32 @@
     for SOCKADDR_INs use record
       Family  at 0 range 0 .. 15;
       Port    at 2 range 0 .. 15;
-      Address at 4 range 0 .. 31;
-      Extra   at 8 range 0 .. 8*8-1;
+      Address at 4 range 0 .. 63;
+      Extra   at 12 range 0 .. 8*8-1;
     end record;
-    for SOCKADDR_INs'size use 16*8;
+    for SOCKADDR_INs'size use 160;
 
     function Connect(S      : Socket_Handles;
                      Name   : access SOCKADDR_INs;
                      Length : Claw.Int := SOCKADDR_INs'size/8)
              return Claw.Int;
-    pragma Import(Stdcall, Connect, "connect");
+    pragma Import(C, Connect, "connect");
 
     function Bind(S       : Socket_Handles;
                   Address : access SOCKADDR_INs;
                   Length  : Claw.Int := SOCKADDR_INs'size/8)
              return Claw.Int;
-    pragma Import(Stdcall, Bind, "bind");
+    pragma Import(C, Bind, "bind");
 
     function Listen(S   : Socket_Handles;
                     Q_Length : Claw.Int) return Claw.Int;
-    pragma Import(Stdcall, Listen, "listen");
+    pragma Import(C, Listen, "listen");
 
     function Accept_function(S       : Socket_Handles;
                              Address : access SOCKADDR_INs;
                              Length  : access Claw.Int)
                return Socket_Handles;
-    pragma Import(Stdcall, Accept_function, "accept");
+    pragma Import(C, Accept_function, "accept");
 
     type Protocol_Type is new Claw.Int;
     Ipproto_TCP : constant Protocol_Type := 6;
@@ -898,7 +889,7 @@
                              Kind    : Sock_Type;
                              Protocol: Protocol_Type)
                return Socket_Handles;
-    pragma Import(Stdcall, Socket_function, "socket");
+    pragma Import(C, Socket_function, "socket");
 
     FD_SETSIZE : constant := 64;
 
@@ -932,10 +923,10 @@
                              Exceptions_FD_Set : access FD_SET_Type;
                              Timeout           : access Timeval_Type)
              return Claw.Int;
-    pragma Import(Stdcall, Select_function, "select");
+    pragma Import(C, Select_function, "select");
 
     function closesocket(s: Socket_Handles) return Claw.Int;
-    pragma Import(Stdcall, closesocket, "closesocket");
+    pragma Import(C, closesocket, "close");
 
     function recv(
                 s    : Socket_Handles;
@@ -943,7 +934,7 @@
                 Len  : Claw.Int;
                 Flags: Claw.Int)
                return Claw.Int;
-    pragma Import(Stdcall, recv, "recv");
+    pragma Import(C, recv, "recv");
 
     function recvfrom(
                 s    : Socket_Handles;
@@ -953,7 +944,7 @@
                 Name   : access SOCKADDR_INs;
                 Length : access Claw.Int)
                return Claw.Int;
-    pragma Import(Stdcall, recvfrom, "recvfrom");
+    pragma Import(C, recvfrom, "recvfrom");
 
     function send(
                 s    : Socket_Handles;
@@ -961,7 +952,7 @@
                 Len  : Claw.Int;
                 Flags: Claw.Int)
                return Claw.Int;
-    pragma Import(Stdcall, send, "send");
+    pragma Import(C, send, "send");
 
     function sendto(
                 s    : Socket_Handles;
@@ -971,7 +962,7 @@
                 Name   : access SOCKADDR_INs;
                 Length : Claw.Int := SOCKADDR_INs'size/8)
                return Claw.Int;
-    pragma Import(Stdcall, sendto, "sendto");
+    pragma Import(C, sendto, "sendto");
 
     type Event_Type is new Claw.uint;
     FD_READ_Event    : constant Event_Type := 1;
@@ -984,12 +975,12 @@
     function getpeername(s : Socket_Handles;
                          Address: access SOCKADDR_INs;
                          Length  : access Claw.Int) return Claw.Int;
-    pragma Import(Stdcall, getpeername, "getpeername");
+    pragma Import(C, getpeername, "getpeername");
 
     function getsockname(s : Socket_Handles;
                          Address: access SOCKADDR_INs;
                          Length  : access Claw.Int) return Claw.Int;
-    pragma Import(Stdcall, getsockname, "getsockname");
+    pragma Import(C, getsockname, "getsockname");
 
     type ioctl_cmd_type is new Claw.DWord;
 
@@ -998,7 +989,7 @@
     function ioctlsocket(s   : Socket_Handles;
                          cmd : ioctl_cmd_type;
                          arg : access Claw.DWord) return Claw.Int;
-    pragma Import(Stdcall, ioctlsocket, "ioctlsocket");
+    pragma Import(C, ioctlsocket, "ioctl");
 
   end Low_Level;
 
diff -r f734a2862510 -r 2cca25a3f5f4 nc.ads
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nc.ads	Wed Dec 22 18:05:52 2010 +0200
@@ -0,0 +1,19 @@
+with Interfaces.C;
+package NC is
+  type Short is new Interfaces.C.Short;
+  type Int is new Interfaces.C.Int;
+  subtype Natural_Int is Int range 0 .. Int'last;
+  type UInt is new Interfaces.C.Unsigned;
+  type DWord is new Interfaces.C.Unsigned_Long;
+
+  type Byte is range 0 .. 255;
+  for Byte'size use 8;
+  type Word is mod 2**16;
+  for Word'size use 16;
+
+  Windows_Error,
+  Not_Valid_Error,
+  Already_Valid_Error,
+  Not_Found_Error : Exception;
+  type Lpcstr is access all Interfaces.C.Char;
+end NC;


-- 
Tero Koskinen - http://iki.fi/tero.koskinen/



^ permalink raw reply	[relevance 14%]

* Re: An Example for Ada.Execution_Time
  2010-12-30 23:51  1%     ` BrianG
@ 2011-01-01  0:07  0%       ` Randy Brukardt
  0 siblings, 0 replies; 200+ results
From: Randy Brukardt @ 2011-01-01  0:07 UTC (permalink / raw)


"BrianG" <briang000@gmail.com> wrote in message 
news:ifj5u9$rr5$1@news.eternal-september.org...
> Randy Brukardt wrote:
>> "BrianG" <briang000@gmail.com> wrote in message 
>> news:ifbi5c$rqt$1@news.eternal-september.org...
>> ...
>>>    >Neither Execution_Time or Execution_Time.Timers provides any value
>>>    >that can be used directly.
>>
>> This seems like a totally silly question. Giving this some sort of 
>> religious importance is beyond silly...
>>
>>                                    Randy.
>
>
> Apparently, asking how a package, defined in the standard, was intended to 
> be used is now a silly question, and asking for an answer to the question 
> I originally asked (which was to clarify a previous response, not to 
> provide an example of use) is a religious debate.  I need to revise my 
> definitions.

But you didn't ask how a package defined in the standard was intended to be 
used. You asked why you have to use another package (Ada.Real_Time) in order 
for it to be useful. And you've repeated that over and over and over like it 
was meaningful in some way. But that is pretty much the definition of a 
silly question. It's just the way the package was defined, and it doesn't 
matter beyond having to add one additional "with" clause.

And that's pretty much irrelevant. In real Ada programs, there are many with 
clauses in the average compilation unit. In Janus/Ada, the number of withs 
averages 20 or so, and Claw programs are much higher than that. One could 
reduce those numbers by putting everything into a few massive packages, but 
those would be unweldy, poorly encapuslated, and close to unmaintainable.

The need to add one extra with to use a real-time package just falls into 
the noise. Probably it would have been better to offer the option of 
retrieving a value in terms of Duration, but it is just not a significant 
difference.

The answer to the "how do you use" question is simple and has been provided 
many times: use "-" to get a Time_Span, operate on that, and why that would 
be a problem to you or anyone else is beyond my comprehension.

> I won't claim to be an expert on the RM, but I don't recall any other 
> package (I did look at the ones you mention) that define a private type 
> but don't provide operations that make that type useful (for some 
> definition of 'use').  Ada.Directories doesn't require Ada.IO_Exceptions 
> to use Directory_Entry_Type or Search_Type; Ada.Streams.Stream_IO doesn't 
> require Ada.Streams (or Ada.Text_IO) to Create/Open/Read/etc. a File_Type. 
> The only thing provided from a CPU_Time is a count in seconds, or another 
> private type.

Here I completely disagree. If you plan to do anything *practical* with the 
Ada.Directories types, you'll have to use another package (at least 
Ada.Text_IO) to do something with the results. (Indeed, that is true of 
*all* Ada packages -- you have to do I/O somewhere or the results are 
irrelevant.  And you are wrong about Stream_IO.Read; you have to use a 
Stream_Element_Array in order to do that, and that is in Ada.Streams, not in 
Stream_IO.

In any case, I'm done wasting my time answering this question. It's obvious 
that you have lost you mind vis-a-vis this question, and there is no reason 
to waste any more time if/until you get it back. Do not feed the troll (even 
if the troll is someone that is otherwise reasonable).

                                                    Randy.





^ permalink raw reply	[relevance 0%]

* Re: An Example for Ada.Execution_Time
  2010-12-29  3:10  2%   ` Randy Brukardt
@ 2010-12-30 23:51  1%     ` BrianG
  2011-01-01  0:07  0%       ` Randy Brukardt
  0 siblings, 1 reply; 200+ results
From: BrianG @ 2010-12-30 23:51 UTC (permalink / raw)


Randy Brukardt wrote:
> "BrianG" <briang000@gmail.com> wrote in message 
> news:ifbi5c$rqt$1@news.eternal-september.org...
> ...
>>    >Neither Execution_Time or Execution_Time.Timers provides any value
>>    >that can be used directly.
> 
> This seems like a totally silly question. 
> 
> Giving this some sort of religious importance is beyond 
> silly...
> 
>                                    Randy.


Apparently, asking how a package, defined in the standard, was intended 
to be used is now a silly question, and asking for an answer to the 
question I originally asked (which was to clarify a previous response, 
not to provide an example of use) is a religious debate.  I need to 
revise my definitions.

I won't claim to be an expert on the RM, but I don't recall any other 
package (I did look at the ones you mention) that define a private type 
but don't provide operations that make that type useful (for some 
definition of 'use').  Ada.Directories doesn't require Ada.IO_Exceptions 
to use Directory_Entry_Type or Search_Type; Ada.Streams.Stream_IO 
doesn't require Ada.Streams (or Ada.Text_IO) to Create/Open/Read/etc. a 
File_Type.  The only thing provided from a CPU_Time is a count in 
seconds, or another private type.

Since D.16 defines CPU_Time as if it were a numeric value, is it too 
much to ask why a conversion to some form of numeric value wasn't 
provided?  Perhaps either a "-" or To_Duration  (and before anyone 
mentions duplicating the existing function, look at all of the 
Open/Close/Create/etc. for all the *_IO File_Types)?  I wasn't asking 
for anything to be changed, merely "why" - because I originally thought 
there might be some use that I hadn't foreseen.  Apparently not.

(Give the RM definition, making it a child of Real_Time might make it 
seem more logical, I guess, but since CPU_Time is not really a time, and 
is not related to "real time" that doesn't seem to make any sense.  I 
would think that would be all the more reason not to relate it to 
Ada.Real_Time.)

--BrianG

-- don't ask me
-- I'm just improvising
--   my illusion of careless flight
-- can't you see
--   my temperature's rising
-- I radiate more heat than light



^ permalink raw reply	[relevance 1%]

* Re: An Example for Ada.Execution_Time
  @ 2010-12-29  3:10  2%   ` Randy Brukardt
  2010-12-30 23:51  1%     ` BrianG
  0 siblings, 1 reply; 200+ results
From: Randy Brukardt @ 2010-12-29  3:10 UTC (permalink / raw)


"BrianG" <briang000@gmail.com> wrote in message 
news:ifbi5c$rqt$1@news.eternal-september.org...
...
> I asked for:
>    >> An algorithm comparison program might look like:
>    >>
>    >> with Ada.Execution_Time ;
>    >> with Ada.Execution_Time.Timers ;
>    >Given the below program, please add some of the missing details to
>    >show how this can be useful without also "with Ada.Real_Time".
>    >Neither Execution_Time or Execution_Time.Timers provides any value
>    >that can be used directly.

This seems like a totally silly question. There are a lot of well-designed 
packages in Ada that don't do anything useful without at least one or more 
other packages. Indeed, if you consider "Standard" to be a separate package 
(and it is), there are hardly any packages that *don't* require some other 
package to be useful.

More to the point, you probably need Ada.IO_Exceptions to use 
Ada.Directories effectively (use of any package without error handling is 
toy use); Ada.Streams.Stream_IO require use of Ada.Streams (a separate 
package, which you will need separate use clauses for even if you get it 
imported automatically); Ada.Strings.Maps aren't useful for anything unless 
you combine them with one of the string handling packages, and so on.

Perhaps you would have been happier if Ada.Execution_Time had been a child 
of Ada.Real_Time (exactly as in the string case), but this wouldn't change 
anything.

The odd thing is that Duration is defined in Standard, rather than some more 
appropriate package. Giving this some sort of religious importance is beyond 
silly...

                                   Randy.





^ permalink raw reply	[relevance 2%]

* Re: Binary opperations under Ada?
  @ 2010-08-21  0:17  2% ` Jeffrey Carter
  0 siblings, 0 replies; 200+ results
From: Jeffrey Carter @ 2010-08-21  0:17 UTC (permalink / raw)


On 08/20/2010 04:23 PM, Trogdor wrote:
>
> -) I want to read in a raw binary file and perform bit manipulation
> on the data.
>
> -) I vaguely remember seeing a post about a module package for low
> level stuff, cut han no longer find it in the group.

For I/O, you may be thinking of seqeuntial or direct I/O, or streams. You can 
find the packages Ada.Sequential_IO, Ada.Direct_IO, and Ada.Streams.Stream_IO in 
the ARM, Annex A, which is quite readable:

http://www.adaic.org/standards/05rm/html/RM-TOC.html

For bit manipulation, you can use (packed) arrays of Boolean or modular types. 
The former existed in Ada 83 and the latter were introduced in Ada 95; both 
should be covered in any good text.

But it's better to talk about what you want to do than how you think you should 
do it. Sometimes you might find a better way to do something.


"I would never want to belong to any club that
would have someone like me for a member."
Annie Hall
41

--- news://freenews.netfront.net/ - complaints: news@netfront.net ---



^ permalink raw reply	[relevance 2%]

* Re: S-expression I/O in Ada
    @ 2010-08-12 23:26  1% ` Shark8
  1 sibling, 0 replies; 200+ results
From: Shark8 @ 2010-08-12 23:26 UTC (permalink / raw)


Natacha,

I took a bit of a stab at writing an SExpression handler, note that
it's not a parser [text-file -> SExpression] but rather what (I think)
you were terming in-memory. It has stream-support so you can directly
save/load an SExpression's structure & contents and it should be easy
to make it "parenthesis preservative" in the parser if you so desire.

I [semi-]plan on making a child-package for the parser "package
SExpression.Text" or somesuch for storing/loading the SExpressions
from text [that is, parsing them].

---------------------------------------------
-- SExpression.ads
---------------------------------------------

With
 Ada.Streams,
 Ada.Streams.Stream_IO;


Package SExpression is

   Type Byte is mod 2**8;
    For Byte'Size use 8;

   Type Binary_Data_Type is Array( Positive Range <> ) Of Byte;
     Pragma Pack(Binary_Data_Type);

   Type Node_Data_Type is ( Binary_Data, String_Data, Number_Data );
   Type Node_Type( Data_Type : Node_Data_Type ) is private;
     Procedure Create( Node: out Node_Type; Data: in
String           );
     Procedure Create( Node: out Node_Type; Data: in
Binary_Data_Type );
     Procedure Create( Node: out Node_Type; Data: in
Long_Integer     );

   Type List_Type;
   Type SExpression_Type(List_Size : Natural) is private;
     Function Is_List ( SExp : in SExpression_Type) Return Boolean;
     Function Create  ( Node : Node_Type ) Return SExpression_Type;
     Procedure Append ( SExp : in out SExpression_Type; Node :
Node_Type );
     Procedure Append ( Front: in out SExpression_Type;
                        Back : in     SExpression_Type );
     Procedure Prepend( SExp : in out SExpression_Type; Node :
Node_Type );
     Procedure Prepend( Front: in     SExpression_Type;
                        Back : in out SExpression_Type );

   Type List_Type is Array(Positive Range <>) of
        Not Null Access SExpression_Type;

     Procedure Create( SExp : out SExpression_Type; List : in
List_Type );

   Package Stream is
      Use Ada.Streams;

      Procedure Write_Bin ( Stream: Not Null Access
Root_Stream_Type'Class;
			    Item : in Binary_Data_Type );
      Procedure Read_Bin  ( Stream: Not Null Access
Root_Stream_Type'Class;
			    Item : out Binary_Data_Type );

      Procedure Write_Node( Stream: Not Null Access
Root_Stream_Type'Class;
			    Item : in Node_Type );
      Procedure Read_Node ( Stream: Not Null Access
Root_Stream_Type'Class;
			    Item : out Node_Type );

      Procedure Write_Sexp( Stream: Not Null Access
Root_Stream_Type'Class;
			    Item : in SExpression_Type );
      Procedure Read_SExp ( Stream: Not Null Access
Root_Stream_Type'Class;
			    Item : out SExpression_Type );

      Procedure Write_List( Stream: Not Null Access
Root_Stream_Type'Class;
			    Item : in List_Type );
      Procedure Read_List ( Stream: Not Null Access
Root_Stream_Type'Class;
			    Item : out List_Type );

   end Stream;


private


   Type Node_Type( Data_Type : Node_Data_Type ) is Record
      case Data_Type is
         when Binary_Data => B : Access Binary_Data_Type;
         when String_Data => S : Access String;
         when Number_Data => N : Long_Integer;
      end case;
   end record;

    For Node_Type'Write use Stream.Write_Node;
    For Node_Type'Read  use Stream.Read_Node;

   Type SExpression_Type(List_Size : Natural) is Record
      case List_Size is
         when 0      => Data: Not Null Access Node_Type;
         when others => List: List_Type(1..List_Size);
      end case;
   end record;

    For SExpression_Type'Read  use Stream.Read_SExp;
    For SExpression_Type'Write use Stream.Write_SExp;

    For List_Type'Read  use Stream.Read_List;
    For List_Type'Write use Stream.Write_List;

    For Binary_Data_Type'Read  use Stream.Read_Bin;
    For Binary_Data_Type'Write use Stream.Write_Bin;
end SExpression;

---------------------------------------------
-- SExpression.adb
---------------------------------------------

Package body SExpression is

   -- Internal Node-Creation Functions.
   Function Make_Node( Data: String ) Return Node_Type is
   begin
      Return Result: Node_Type( Data_Type => String_Data ) do
         Result.S:= New String'(Data);
      end Return;
   end Make_Node;

   Function Make_Node( Data: Binary_Data_Type ) Return Node_Type is
   begin
      Return Result: Node_Type( Data_Type => Binary_Data ) do
         Result.B:= New Binary_Data_Type'(Data);
      end Return;
   end Make_Node;

   Function Make_Node( Data: Long_Integer ) Return Node_Type is
   begin
      Return Result: Node_Type( Data_Type => Number_Data ) do
         Result.N:= Data;
      end Return;
   end Make_Node;


   -- Public Node-Creation Procedures {wraps node-creation functions}
   Procedure Create ( Node: out Node_Type; Data: in String ) is
   begin
      Node:= Make_Node(Data);
   end Create;

   Procedure Create ( Node: out Node_Type; Data: in Binary_Data_Type )
is
   begin
      Node:= Make_Node( Data );
   end Create;

   Procedure Create ( Node: out Node_Type; Data: in Long_Integer ) is
   begin
      Node:= Make_Node(Data);
   end Create;

Pragma Inline( Create );

   Function Is_List(SExp : in SExpression_Type) Return Boolean is
   begin
      Return SExp.List_Size > 0;
   end Is_List;
   Pragma Inline(Is_List);

   Function Create( List : in List_Type ) Return SExpression_Type is
   begin
      Return Result: SExpression_Type( List_Size => List'Length ) do
         Result.List:= List;
      end return;
   end Create;

   Procedure Create( SExp : out SExpression_Type; List : in
List_Type ) is
   begin
      SExp:= Create( List );
   end Create;

   Function Create( Node : Node_Type ) Return SExpression_Type is
   begin
      Return Result : SExpression_Type( List_Size => 0 ) do
         Result.Data:= New Node_Type'( Node );
      end return;
   end Create;

   Procedure Append ( SExp : in out SExpression_Type; Node :
Node_Type ) is
   begin
      if Is_List(SExp) then
         SExp:= Create( Sexp.List & New
SExpression_Type'(Create(Node)) );
      else
         SExp:= Create(   New
SExpression_Type'(Create(SExp.Data.All))
			& New SExpression_Type'(Create(Node))
		      );
      end if;
   end Append;

   Procedure Prepend( SExp : in out SExpression_Type; Node :
Node_Type ) is
   begin
      if Is_List(SExp) then
         SExp:= Create( New SExpression_Type'(Create(Node)) &
Sexp.List);
      else
         SExp:= Create(   New SExpression_Type'(Create(Node))
			& New SExpression_Type'(Create(SExp.Data.All))
		      );
      end if;
   end Prepend;

   Procedure Append ( Front: in out SExpression_Type;
		      Back : in     SExpression_Type ) is
   begin
      if Is_List(Back) then
         Front:= Create( Front.List & Back.List);
      else
         Append( SExp => Front, Node => Back.Data.All );
      end if;
   end Append;

   Procedure Prepend( Front: in     SExpression_Type;
		      Back : in out SExpression_Type ) is
   begin
      if Is_List(Front) then
         Back:= Create( Front.List & Back.List);
      else
         Prepend( SExp => Back, Node => Front.Data.All );
      end if;
   end Prepend;

   package body Stream is
      Procedure Write_Bin ( Stream: Not Null Access
Root_Stream_Type'Class;
			    Item : in Binary_Data_Type ) is
      begin
         Positive'Write( Stream, Item'Length );
         For Index in Item'Range loop
            Byte'Write( Stream, Item(Index) );
         end loop;
      end Write_Bin;

      Procedure Read_Bin  ( Stream: Not Null Access
Root_Stream_Type'Class;
                           Item : out Binary_Data_Type ) is

         Function Get_Elements( Length: Positive ) Return
Binary_Data_Type is
         begin
            Return Result: Binary_Data_Type(1..Length) do
               For Index in Result'Range loop
                  Byte'Read( Stream, Result(Index) );
               end loop;
            end Return;
         end Get_Elements;

         Length: Positive;
      begin
         Positive'Read( Stream, Length );
         Item:= Get_Elements( Length );
      end Read_Bin;


      Procedure Write_Node( Stream: Not Null Access
Root_Stream_Type'Class;
			    Item : in Node_Type ) is
      begin
         Node_Data_Type'Write( Stream, Item.Data_Type );

         Case Item.Data_Type is
            When Binary_Data => Binary_Data_Type'Write( Stream,
Item.B.All );
            When String_Data => String'Write( Stream, Item.S.All );
            When Number_Data => Long_Integer'Write( Stream, Item.N );
         end Case;
      end Write_Node;

      Procedure Read_Node ( Stream: Not Null Access
Root_Stream_Type'Class;
			    Item : out Node_Type ) is
         Data_Type : Node_Data_Type;
      begin
         Node_Data_Type'Read( Stream, Data_Type );

            Case Data_Type is
            When Binary_Data =>
               Item.B:= New Binary_Data_Type'( 1..0 => <> );
               Declare
                  Binary_Temp  : Access Binary_Data_Type:=
                    New Binary_Data_Type'( 1..0 => 16#FF# );
               Begin
                  Binary_Data_Type'Read( Stream, Binary_Temp.All );
                  Item:= Make_Node( Data => Binary_Temp.All );
               End;
            When String_Data =>
               declare
                  String_Temp  : Access String:= New String'("");
               begin
                  String'Read( Stream, String_Temp.All);
                  Item:= Make_Node( Data => String_Temp.All );
               end;
            When Number_Data =>
               declare
                  Temp : Long_Integer;
               begin
                  Long_Integer'Read( Stream, Temp );
                  Item:= Make_Node( Temp );
               end;
            end Case;
      end Read_Node;




      Procedure Write_SExp( Stream: Not Null Access
Root_Stream_Type'Class;
			    Item : in SExpression_Type ) is
      begin
         Natural'Write( Stream, Item.List_Size );
         if Item.List_Size = 0 then
            Node_Type'Write( Stream, Item.Data.All );
         else
            List_Type'Write( Stream, Item.List );
         end if;
      end Write_SExp;

      Procedure Read_SExp ( Stream: Not Null Access
Root_Stream_Type'Class;
			    Item : out SExpression_Type ) is
         List_Size : Natural;
      begin
         Natural'Read( Stream, List_Size );
         if List_Size = 0 then
            Declare
               Temp : Access Node_Type:= New
Node_Type'( Make_Node(0) );
            Begin
               Node_Type'Read( Stream, Temp.All );
               Item:= Create( Temp.All );
            End;
         else
            Declare
               Dummy: Aliased SExpression_Type:=
Create(Make_Node(0));
               Temp : List_Type:= (1..List_Size =>
Dummy'Unchecked_Access );
            Begin
               List_Type'Read( Stream, Temp );
               Item:= Create( Temp );
            End;
         end if;
      end Read_SExp;


      Procedure Write_List( Stream: Not Null Access
Root_Stream_Type'Class;
			    Item : in List_Type ) is
      begin
         Positive'Write(Stream, Item'Length);
         For Index in Item'Range loop
            SExpression_Type'Write( Stream, Item(Index).All );
         end loop;
      end Write_List;

      Procedure Read_List ( Stream: Not Null Access
Root_Stream_Type'Class;
			    Item : out List_Type ) is

         Function Get_Elements( Length: Positive ) Return List_Type is
            Working : Access SExpression_Type;
         begin
            Working:= New SExpression_Type'( Create(Make_Node(0)) );
            Return Result: List_Type(1..Length) do
               For Index in Result'Range loop
                  SExpression_Type'Read( Stream, Working.All );
                  Result(Index):= New
SExpression_Type'( Working.All );
               end loop;
            end Return;
         end Get_Elements;

         Length : Positive;
      begin
         Positive'Read(Stream, Length);
         Item:= Get_Elements( Length );
      end Read_List;


   end Stream;

end SExpression;



^ permalink raw reply	[relevance 1%]

* Re: S-expression I/O in Ada
  @ 2010-08-12 10:55  1%                 ` Ludovic Brenta
  0 siblings, 0 replies; 200+ results
From: Ludovic Brenta @ 2010-08-12 10:55 UTC (permalink / raw)


Natacha Kerensikova wrote on comp.lang.ada:
[...]
> Sexp_Stream is supposed to perform S-expression I/O over streams,
> without ever constructing a S-expression into memory. It is supposed
> to do only the encoding and decoding of S-expression format, to expose
> its clients only atoms and relations.

But how can it expose atoms and relations without an in-memory tree
representation? Honestly, I do not think that such a concept is
viable. Hence, the "S-Expression stream" must actually depend on the
in-memory tree representation, both for reading and for writing. That
is whay my package does.

> A further unnamed yet package would handle the memory representation
> of S-expressions, which involve object creation, memory management and
> things like that. It would be a client of Sexp_Stream for I/O, so the
> parsing would only be done at one place (namely Sexp_Stream). As I
> said Ludovic Brenta's code might take this place.

No, it replaces both of your hypothetical packages and I don't think
you can have the "stream" package without the "S-Expression" package.
You could, however, have an S-Expression package without any I/O.

> There are situations when a memory representation of S-expressions is
> not needed, and the tcp-connect example here seems to be such a case.
> That's why I imagined TCP_Info as a client of Sexp_Stream instead of a
> client of the second package.

If no S-Expressions are needed in memory, then your entire data is
just one big unstructured String, and you cannot parse it into a
TCP_Info record unless you re-introduce the S-Expression tree in
memory.

>> I think the client should just do
>>
>> S : S_Expression := Some_Initialization;
>>
>> Put (File => F, Expression => S);
>
> To achieve such an interface, the client has to build an in-memory S-
> expression object. In the tcp-connect example, there are eight nodes
> (five atoms and three lists). They have to be somehow built, and it
> doesn't look like a simple initialization.
>
> The second interface I proposed, with a lot of nested calls, builds
> the S-expression object with functions looking like:
> function NewList(Contents, Next: S_node_access) return S_node_access;
> function AtomFromWhatever(Contents: whatever, Next: S_node_access)
> return S_node_access;

That's what I do in the test.adb example (using Cons () and To_Atom ()
respectively).

> However, unless I'm building other higher-level functions, to build 8
> nodes I need 8 function calls, exactly like the second example.
>
> That 8-function-call example looks very C-ish to me, and honestly I
> don't like it, I prefer the sequence of procedure calls from
> Sexp_Stream example, but that's just a personal taste.
>
> The problem is that I don't see how to do it otherwise. Any idea would
> be welcome.

Here is one idea: embed the S-Expression "language" in Ada:

function To_Sexp (S : in String) return S_Expression.T is
  String_Stream : constant Ada.Streams.Stream_IO.Stream_Access :=
     Stream_Reading_From (S); -- implementation left as an exercise :)
begin
   return Result : S_Expression.T do
      S_Expression.T'Read (String_Stream, Result);
   end return;
end To_Sexp;

TCP_Info : constant String := "(tcp-connect (host foo.bar) (port
80))";
TCP_Info_Structured := constant To_TCP_Info (To_Sexp (TCP_Info));

(this is based on my implementation).

>> Your TCP_Info-handling pkg would convert the record into an S-expression, and
>> call a single operation from your S-expression pkg to output the S-expression.
>
> That's the tricky part. At least so tricky that I can't imagine how to
> do it properly.

Yes, the S_Expression.Read operation is quite involved. But it can be
done, and has been done :)

--
Ludovic Brenta.




^ permalink raw reply	[relevance 1%]

* Re: Why is not Stream_Access defined Ada.Streams ?
  2010-05-07  1:02  2% Why is not Stream_Access defined Ada.Streams ? Yannick Duchêne (Hibou57)
@ 2010-05-07  2:24  0% ` Randy Brukardt
  0 siblings, 0 replies; 200+ results
From: Randy Brukardt @ 2010-05-07  2:24 UTC (permalink / raw)


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain, Size: 950 bytes --]

"Yannick Duch�ne (Hibou57)" <yannick_duchene@yahoo.fr> wrote in message 
news:op.vca852lexmjfy8@garhos...
> Hi all and Hi others as well,
>
> My dirty stuff of the day : why is Stream_Access not defined once a time 
> in Ada.Streams and is instead defined elsewhere multiple times, like in 
> Ada.Streams.Stream_IO, Ada.Text_IO.Text_Streams, 
> Ada.Wide_Text_IO.Text_Streams and Ada.Wide_Wide_Text_IO.Text_Streams ?
>
> Isn't it funny design ?

Ada 95 didn't have anonymous access returns, so a named type had to be 
defined. I suspect that there was no intent that it be used for anything 
other than defining the result of these functions -- and there was no intent 
that that result be stored: just directly dereferenced and passed to a 
stream attribute.

If we were writing it today, I'm pretty sure that no named type would be 
used at all. But making a change like that now would be incompatible.

                                Randy.





^ permalink raw reply	[relevance 0%]

* Why is not Stream_Access defined Ada.Streams ?
@ 2010-05-07  1:02  2% Yannick Duchêne (Hibou57)
  2010-05-07  2:24  0% ` Randy Brukardt
  0 siblings, 1 reply; 200+ results
From: Yannick Duchêne (Hibou57) @ 2010-05-07  1:02 UTC (permalink / raw)


Hi all and Hi others as well,

My dirty stuff of the day : why is Stream_Access not defined once a time  
in Ada.Streams and is instead defined elsewhere multiple times, like in  
Ada.Streams.Stream_IO, Ada.Text_IO.Text_Streams,  
Ada.Wide_Text_IO.Text_Streams and Ada.Wide_Wide_Text_IO.Text_Streams ?

Isn't it funny design ?

-- 
No-no, this isn't an oops ...or I hope (TM) - Don't blame me... I'm just  
not lucky



^ permalink raw reply	[relevance 2%]

* Problem with streams using 64-bit compiler
@ 2010-01-04 22:46  2% sjw
  0 siblings, 0 replies; 200+ results
From: sjw @ 2010-01-04 22:46 UTC (permalink / raw)


While trying to build a 64-bit compiler for Mac OS X Snow Leopard, I
came across this undesirable behaviour: if the program (see end) is
compiled in 32-bit mode or in 64-bit mode with -O0 it works fine,
output is as expected:

$ ./streamy
 1234
'z'
 4.32100E-01
 4.32100E-01

If compiled in 64-bit mode with -O2, output is

$ ./streamy
1234
NUL
 0.00000E+00
 0.00000E+00

This is a readback problem, the data file has the same content in all
cases.

Can anyone with access to an x86_64 compiler (Mac OS X Leopard, or a
Linux, 4.4+) have a try and see what happens?

Thanks in advance,

--S

--------------------------------------------------
with Ada.Text_IO; use Ada.Text_IO;
with Ada.Streams.Stream_IO;

procedure Streamy is

   type Kind is (I, C, F);

   type Item (Of_Kind : Kind := I) is record
      case Of_Kind is
         when I => I : Integer;
         when C => C : Character;
         when F => F : Float;
      end case;
   end record;

   File : Ada.Streams.Stream_IO.File_Type;

   use Ada.Streams.Stream_IO;

begin

   Create (File, Name => "test.dat");

   Reset (File, Mode => Out_File);
   Item'Output (Stream (File), Item'(I, 1234));
   Item'Output (Stream (File), Item'(C, 'z'));
   Item'Output (Stream (File), Item'(F, 0.4321));

   Reset (File, Mode => In_File);
   for N in 1 .. 3 loop
      declare
         It : constant Item := Item'Input (Stream (File));
      begin
         case It.Of_Kind is
            when I =>
               Put_Line (It.I'Img);
            when C =>
               Put_Line (It.C'Img);
            when F =>
               Put_Line (It.F'Img);
         end case;
      end;
   end loop;

   Reset (File, Mode => Out_File);
   Item'Write (Stream (File), Item'(F, 0.4321));

   Reset (File, Mode => In_File);
   declare
      Flt : Item (F);
   begin
      Item'Read (Stream (File), Flt);
      Put_Line (Flt.F'Img);
   end;

end Streamy;



^ permalink raw reply	[relevance 2%]

* Re: Performance of the Streams 'Read and 'Write
  2009-10-30 13:40  2% ` Gautier write-only
@ 2009-11-02 22:19  2%   ` Gautier write-only
  0 siblings, 0 replies; 200+ results
From: Gautier write-only @ 2009-11-02 22:19 UTC (permalink / raw)


Here is the ultimate test ;-), with Jeff's overlay idea and the
unchecked_conversion as well.
G.

-- Usage: test_stream_performance <big_file>
-- Produces .tmp files that are copies of <big_file>.
--
-- Example of output with GNAT GPL 2008 / Win32:
--
--  xxx'Write / xxx'Read (Stream attributes)......... 9.282530042
seconds
--  Workarounds with Stream_Element_Array buffer:
--    copy........................................... 0.444120412
seconds
--    overlay (read), unchecked_conversion (write)... 0.156874407
seconds
--    overlay........................................ 0.150155676
seconds
--  Factor (Copy)    20.900930898
--  Factor (Overlay) 61.819374993

--  Buffer size in bits..... 8192
--  SE Buffer size in bits.. 8192

--  File size in megabytes..... 2.46367E+01

with Ada.Calendar;                      use Ada.Calendar;
with Ada.Text_IO;
with Ada.Streams.Stream_IO;             use Ada.Streams.Stream_IO;
with Ada.Command_Line;                  use Ada.Command_Line;
with Ada.Unchecked_Conversion;
with Interfaces;                        use Interfaces;

procedure Test_Stream_Performance is

  f_in, f_out: Ada.Streams.Stream_IO.File_Type;

  buffer_size, SE_buffer_size: Natural:= 0;
  -- To check if buffers are binary compatible (same packing)

  type Buffer is array(Natural range <>) of Unsigned_8;

  ------------------------------------------------
  -- 1) Stream attributes - xxx'Read, xxx'Write --
  ------------------------------------------------

  -- NB: usually we would just have: Buffer'Read(Stream(f_in), b);
  -- Here we care about end of file.
  --
  procedure Read_Attribute( b: out Buffer; last_read: out Natural ) is
    idx: constant Positive_Count:= Index(f_in);
    siz: constant Positive_Count:= Size(f_in);
  begin
    if End_Of_File(f_in) then
      last_read:= b'First-1;
    else
      last_read:= Natural'Min(b'First+Natural(siz-idx),b'Last);
      Buffer'Read(Stream(f_in), b(b'First .. last_read));
    end if;
  end Read_Attribute;

  procedure Write_Attribute( b: in Buffer ) is
  begin
    if buffer_size = 0 then
      buffer_size:= b'size; -- just for stats
    end if;
    Buffer'Write(Stream(f_out), b);
  end Write_Attribute;

  ---------------------------------------------
  -- 2) The Stream_Element_Array workarounds --
  ---------------------------------------------

  procedure Read_SE_Copy( b: out Buffer; last_read: out Natural ) is
    use Ada.Streams;
    First     : constant Stream_Element_Offset:= Stream_Element_Offset
(b'First);
    Last      :          Stream_Element_Offset:= Stream_Element_Offset
(b'Last);
    SE_Buffer : Stream_Element_Array (First..Last);
  begin
    Read(Stream(f_in).all, SE_Buffer, Last);
    for i in First..Last loop
      b(Natural(i)):= Unsigned_8(SE_Buffer(i));
    end loop;
    last_read:= Natural(last);
  end Read_SE_Copy;

  procedure Write_SE_Copy( b: in Buffer ) is
    use Ada.Streams;
    First     : constant Stream_Element_Offset:= Stream_Element_Offset
(b'First);
    Last      : constant Stream_Element_Offset:= Stream_Element_Offset
(b'Last);
    SE_Buffer : Stream_Element_Array (First..Last);
  begin
    if SE_buffer_size = 0 then
      SE_buffer_size:= SE_Buffer'size; -- just for stats
    end if;
    for i in SE_Buffer'Range loop
      SE_Buffer(i):= Stream_Element(b(Natural(i)));
    end loop;
    Write(Stream(f_out).all, SE_Buffer);
  end Write_SE_Copy;

  -- Overlay idea by Jeff Carter

  procedure Read_SE_Overlay( b: out Buffer; last_read: out Natural )
is
    use Ada.Streams;
    Last: Stream_Element_Offset;
    SE_Buffer : Stream_Element_Array (1..b'Length);
    for SE_Buffer'Address use b'Address;
  begin
    Read(Stream(f_in).all, SE_Buffer, Last);
    last_read:= b'First + Natural(Last) - 1;
  end Read_SE_Overlay;

  procedure Write_SE_Overlay( b: in Buffer ) is
    use Ada.Streams;
    SE_Buffer : Stream_Element_Array (1..b'Length);
    for SE_Buffer'Address use b'Address;
  begin
    Write(Stream(f_out).all, SE_Buffer);
  end Write_SE_Overlay;

  -- Using Unchecked_Conversion

  procedure Write_SE_UC( b: in Buffer ) is
    subtype My_SEA is Ada.Streams.Stream_Element_Array(1..b'Length);
    function To_SEA is new Ada.Unchecked_Conversion(Buffer, My_SEA);
    use Ada.Streams;
  begin
    Write(Stream(f_out).all, To_SEA(b));
  end Write_SE_UC;

  ----------
  -- Test --
  ----------

  function name return String is
  begin
    return Argument(1);
  end;

  generic
    label: String;
    with procedure Read( b: out Buffer; last_read: out Natural  );
    with procedure Write( b: in Buffer  );
  procedure Test;

  procedure Test is
    b: Buffer(1..1024);
    l: Natural;
  begin
    Open(f_in, In_File, name);
    Create(f_out, Out_File, name & "_$$$_" & label & ".tmp");
    while not End_of_File(f_in) loop
      Read(b,l);
      Write(b(1..l));
    end loop;
    Close(f_out);
    Close(f_in);
  end;

  procedure Test_Attribute is new Test("Attribute", Read_Attribute,
Write_Attribute);
  procedure Test_SE_Copy is new Test("SE_Copy", Read_SE_Copy,
Write_SE_Copy);
  procedure Test_SE_Overlay is new Test("SE_Overlay", Read_SE_Overlay,
Write_SE_Overlay);
  procedure Test_SE_UC is new Test("SE_UC", Read_SE_Overlay,
Write_SE_UC);

  T0, T1, T2, T3, T4: Time;

  use Ada.Text_IO;

begin
  if Argument_Count=0 then
    Put_Line(" Usage: test_stream_performance <big_file>");
    Put_Line(" Produces .tmp files that are copies of <big_file>.");
    return;
  end if;
  T0:= Clock;
  Test_Attribute;
  T1:= Clock;
  Test_SE_Copy;
  T2:= Clock;
  Test_SE_Overlay;
  T3:= Clock;
  Test_SE_UC;
  T4:= Clock;
  Put_Line("xxx'Write / xxx'Read (Stream attributes)........." &
Duration'Image(T1-T0) & " seconds");
  Put_Line("Workarounds with Stream_Element_Array buffer:");
  Put_Line("  copy..........................................." &
Duration'Image(T2-T1) & " seconds");
  Put_Line("  overlay (read), unchecked_conversion (write)..." &
Duration'Image(T4-T3) & " seconds");
  Put_Line("  overlay........................................" &
Duration'Image(T3-T2) & " seconds");
  Put_Line("Factor (Copy)   " & Duration'Image((T1-T0)/(T2-T1)));
  Put_Line("Factor (Overlay)" & Duration'Image((T1-T0)/(T3-T2)));
  New_Line;
  Put_Line("Buffer size in bits....." & Integer'Image(buffer_size));
  Put_Line("SE Buffer size in bits.." & Integer'Image
(SE_buffer_size));
  New_Line;
  Open(f_in, In_File, name);
  Put_Line("File size in megabytes....." & Float'Image(Float(Size
(f_in))/(1024.0*1024.0)));
  Close(f_in);
end;




^ permalink raw reply	[relevance 2%]

* Re: Performance of the Streams 'Read and 'Write
  2009-10-29 23:29  1% Performance of the Streams 'Read and 'Write Gautier write-only
@ 2009-10-30 13:40  2% ` Gautier write-only
  2009-11-02 22:19  2%   ` Gautier write-only
  0 siblings, 1 reply; 200+ results
From: Gautier write-only @ 2009-10-30 13:40 UTC (permalink / raw)


Here is a test program. I am curious about other results

-- Usage: test_stream_performance <file>
-- Produces two .tmp files that are copies of <file>.
--
-- Example of output with file m.wmv, 2.59 MB, GNAT GPL 2008 / Win32:
--
--  xxx'Write / xxx'Read (Attribute).. 1.925210886 seconds
--  Workaround with SE buffer......... 0.049318559 seconds
--  Factor 39.036235547

--  Buffer size in bits..... 8192
--  SE Buffer size in bits.. 8192

with Ada.Calendar;                      use Ada.Calendar;
with Ada.Text_IO;
with Ada.Streams.Stream_IO;             use Ada.Streams.Stream_IO;
with Ada.Command_Line;                  use Ada.Command_Line;
with Interfaces;                        use Interfaces;

procedure Test_Stream_Performance is

  f_in, f_out: Ada.Streams.Stream_IO.File_Type;

  buffer_size, SE_buffer_size: Natural:= 0;
  -- To check if buffers could be overlapped (packing)

  type Buffer is array(Natural range <>) of Unsigned_8;

  ------------------------------------------------
  -- 1) Stream attributes - xxx'Read, xxx'Write --
  ------------------------------------------------

  -- Usually we would just have: Buffer'Read(Stream(f_in), b);
  -- Here we care about end of file.

  procedure Read_Attribute( b: out Buffer; last_read: out Natural ) is
    idx: constant Positive_Count:= Index(f_in);
    siz: constant Positive_Count:= Size(f_in);
  begin
    if End_Of_File(f_in) then
      last_read:= b'First-1;
    else
      last_read:= Natural'Min(b'First+Natural(siz-idx),b'Last);
      Buffer'Read(Stream(f_in), b(b'First .. last_read));
    end if;
  end Read_Attribute;

  procedure Write_Attribute( b: in Buffer ) is
  begin
    if buffer_size = 0 then
      buffer_size:= b'size;
    end if;
    Buffer'Write(Stream(f_out), b);
  end Write_Attribute;

  --------------------------------------------
  -- 2) The Stream_Element_Array workaround --
  --------------------------------------------

  procedure Read_SE( b: out Buffer; last_read: out Natural ) is
    use Ada.Streams;
    First     : constant Stream_Element_Offset:= Stream_Element_Offset
(b'First);
    Last      :          Stream_Element_Offset:= Stream_Element_Offset
(b'Last);
    SE_Buffer : Stream_Element_Array (First..Last);
  begin
    Read(Stream(f_in).all, SE_Buffer, Last);
    for i in First..Last loop
      b(Natural(i)):= Unsigned_8(SE_Buffer(i));
    end loop;
    last_read:= Natural(last);
  end Read_SE;

  procedure Write_SE( b: in Buffer ) is
    use Ada.Streams;
    First     : constant Stream_Element_Offset:= Stream_Element_Offset
(b'First);
    Last      : constant Stream_Element_Offset:= Stream_Element_Offset
(b'Last);
    SE_Buffer : Stream_Element_Array (First..Last);
  begin
    if SE_buffer_size = 0 then
      SE_buffer_size:= SE_Buffer'size;
    end if;
    for i in SE_Buffer'Range loop
      SE_Buffer(i):= Stream_Element(b(Natural(i)));
    end loop;
    Write(Stream(f_out).all, SE_Buffer);
  end Write_SE;

  name : constant String:= Argument(1);

  generic
    label: String;
    with procedure Read( b: out Buffer; last_read: out Natural  );
    with procedure Write( b: in Buffer  );
  procedure Test;

  procedure Test is
    b: Buffer(1..1024);
    l: Natural;
  begin
    Open(f_in, In_File, name);
    Create(f_out, Out_File, name & "_$$$_" & label & ".tmp");
    while not End_of_File(f_in) loop
      Read(b,l);
      Write(b(1..l));
    end loop;
    Close(f_out);
    Close(f_in);
  end;

  procedure Test_Attribute is new Test("Attribute", Read_Attribute,
Write_Attribute);
  procedure Test_SE is new Test("SE", Read_SE, Write_SE);

  T0, T1, T2: Time;

  use Ada.Text_IO;

begin
  T0:= Clock;
  Test_Attribute;
  T1:= Clock;
  Test_SE;
  T2:= Clock;
  Put_Line("xxx'Write / xxx'Read (Attribute).." & Duration'Image(T1-
T0) & " seconds");
  Put_Line("Workaround with SE buffer........." & Duration'Image(T2-
T1) & " seconds");
  Put_Line("Factor" & Duration'Image((T1-T0)/(T2-T1)));
  New_Line;
  Put_Line("Buffer size in bits....." & Integer'Image(buffer_size));
  Put_Line("SE Buffer size in bits.." & Integer'Image
(SE_buffer_size));
end;



^ permalink raw reply	[relevance 2%]

* Performance of the Streams 'Read and 'Write
@ 2009-10-29 23:29  1% Gautier write-only
  2009-10-30 13:40  2% ` Gautier write-only
  0 siblings, 1 reply; 200+ results
From: Gautier write-only @ 2009-10-29 23:29 UTC (permalink / raw)


Hello.
I got used to think that I/O was the last spot where our preferred
language was condemned to slowness.
Now consider this. Variant 1 of a buffered I/O:

  type Buffer is array(Natural range <>) of Unsigned_8;

  procedure Read( b: out Buffer ) is
  begin
    Buffer'Read(Stream(f_in), b);
  exception
    when Ada.Streams.Stream_IO.End_Error =>
      null;
      -- Nothing bad, just some garbage in the buffer
      -- after end of compressed code
  end Read;

  procedure Write( b: in Buffer ) is
  begin
    Buffer'Write(Stream(f_out), b);
  end Write;

Bad luck, it is as slow as doing I/O's with single bytes and
Sequential_IO! But if it is slow by receiving/sending a whole buffer,
how to make it faster ? Now someone (in a slightly different context)
came with this (call it variant 2):

  procedure Read( b: out Buffer ) is
    use Ada.Streams;
    First     : constant Stream_Element_Offset:= Stream_Element_Offset
(b'First);
    Last      :          Stream_Element_Offset:= Stream_Element_Offset
(b'Last);
    SE_Buffer : Stream_Element_Array (First..Last);
  begin
    Read(Stream(f_in).all, SE_Buffer, Last);
    for i in First..Last loop
      b(Natural(i)):= Unsigned_8(SE_Buffer(i));
    end loop;
  end Read;

  procedure Write( b: in Buffer ) is
    use Ada.Streams;
    First     : constant Stream_Element_Offset:= Stream_Element_Offset
(b'First);
    Last      : constant Stream_Element_Offset:= Stream_Element_Offset
(b'Last);
    SE_Buffer : Stream_Element_Array (First..Last);
  begin
    for i in SE_Buffer'Range loop
      SE_Buffer(i):= Stream_Element(b(Natural(i)));
    end loop;
    Write(Stream(f_out).all, SE_Buffer);
  end Write;

Naively, you would say it is even slower: you do even more by copying
a buffer into another one, right ?
Indeed, not at all, it is *lots* faster (on GNAT and ObjectAda)!
To give an idea, the variant 1 applied to a bzip2 decompressor makes
it 4x slower than the C version, and variant 2 makes it only 7%
slower! With only I/O (like copying a file) you would get an even much
larger difference.

Now, it raises some questions:
Is there maybe a reason in the RM why the 'Read and 'Write have to be
that slow ?
Or are these two compilers lazy when compiling these attributes ?
Should I bug Adacore about that, then ?
Do some other compilers do it better ?
_________________________________________________________
Gautier's Ada programming -- http://sf.net/users/gdemont/
NB: For a direct answer, e-mail address on the Web site!



^ permalink raw reply	[relevance 1%]

* Re: Preferred way to do binray I/O on standard input/output stream
  @ 2009-10-24 22:57  2% ` Jeffrey R. Carter
  0 siblings, 0 replies; 200+ results
From: Jeffrey R. Carter @ 2009-10-24 22:57 UTC (permalink / raw)


Hibou57 (Yannick Duch�ne) wrote:
> 
> There is no kind of binary mode vs text mode flags with Ada stream/
> file IO, as it there are with C. And then, C files are not typed,
> while Ada files/streams are, thus, this will not make any sense to
> simply talk about binary I/O with Ada. So let simply talk about non-
> text I/O from and to standard input/output.
> 
> When some people need this, what is the typical preferred to do so ?

Package Ada.Text_IO.Text_Streams (ARM A.12.2) allows converting 
Ada.Text_IO.File_Type to Stream_Access and reading and writing them through the 
capabilities of streams. This allows converting standard input and output to 
Stream_Access, since Ada.Text_IO provides the functions Standard_Input and 
Standard_Output which return Ada.Text_IO.File_Type.

For general binary I/O, one can use Ada.Sequential_IO or Ada.Direct_IO 
instantiated with an appropriate type, or Ada.Streams.Stream_IO. For standard 
input and output, however, this can only work if you have a name for these files 
that you can use to open them, and such a name is platform-dependent. The only 
independent way to access these files is through streams and 
Ada.Text_IO.Text_Streams.

-- 
Jeff Carter
"Drown in a vat of whiskey. Death, where is thy sting?"
Never Give a Sucker an Even Break
106



^ permalink raw reply	[relevance 2%]

* Tasking for Mandelbrot program
@ 2009-09-27  1:08  1% Georg Bauhaus
  0 siblings, 0 replies; 200+ results
From: Georg Bauhaus @ 2009-09-27  1:08 UTC (permalink / raw)


A Mandelbrot program has been submitted to the language
Shootout by Jim Rogers, Pascal Obry, and
Gautier de Montmollin.  Given the no tricks approach
that it shares with other entries, it is performing
well, I'd think.  But, it is sequential.

The patch below adds tasking.

A few notes on patch:
The computation is split into parts, one per task;
many entries seem to use a similar approach.
The number of tasks is set high, task switching does
not seem to matter much in this program.
The alternative of making the environment task perform
the same subprogram as the tasks concurrently
and matching the number of tasks to the number of cores
was not significantly faster.  The alternative
spoils the simplicity of the main block, so I set
a higher number of tasks and got basically the same
performance.

Maybe these are possible improvements:

- Ada.Streams.Stream_IO? (In total absence of Text_IO,
  GNAT.IO performs well.)

- adjust compilation options to match the FPT hardware
  (type Real is now digits 16 because of this, cf.
  the spectral-norm entry at the Shootout)

Comments?  Can I ask what the authors think?


pragma Restrictions (No_Abort_Statements);
pragma Restrictions (Max_Asynchronous_Select_Nesting => 0);

with Ada.Command_Line; use Ada.Command_Line;
with Ada.Numerics.Generic_Complex_Types;

with Interfaces;       use Interfaces;
with GNAT.IO;          use GNAT.IO;


procedure Mandelbrot is
   type Real is digits 16;
   package R_Complex is new Ada.Numerics.Generic_Complex_Types (Real);
   use R_Complex;
   Iter           : constant := 50;
   Limit          : constant := 4.0;
   Size           : Positive;
   Zero           : constant Complex := (0.0, 0.0);
   Two_on_Size    : Real;

   subtype Output_Queue is String;
   type Output is access Output_Queue;

   task type X_Step is
      entry Compute_Z (Y1, Y2 : Natural);
      entry Get_Output (Result : out Output; Last : out Natural);
   end X_Step;

   procedure Allocate_Output_Queue (Y1, Y2 : Natural; Result : out Output);

   procedure Compute
     (Y1, Y2 : Natural; Result : Output; Last : out Natural)
   is
      Bit_Num     : Natural    := 0;
      Byte_Acc    : Unsigned_8 := 0;
      Z, C        : Complex;
   begin
      Last := 0;
      for Y in Y1 .. Y2 - 1 loop
         for X in 0 .. Size - 1 loop
            Z := Zero;
            C := Two_on_Size * (Real (X), Real (Y)) - (1.5, 1.0);

            declare
               Z2 : Complex;
            begin
               for I in 1 .. Iter + 1 loop
                  Z2 := (Z.re ** 2, Z.im ** 2);
                  Z  := (Z2.re - Z2.im, 2.0 * Z.re * Z.im) + C;
                  exit when Z2.re + Z2.im > Limit;
               end loop;

               if Z2.re + Z2.im > Limit then
                  Byte_Acc := Shift_Left (Byte_Acc, 1) or 16#00#;
               else
                  Byte_Acc := Shift_Left (Byte_Acc, 1) or 16#01#;
               end if;
            end;

            Bit_Num := Bit_Num + 1;

            if Bit_Num = 8 then
               Last := Last + 1;
               Result (Last) := Character'Val (Byte_Acc);
               Byte_Acc := 0;
               Bit_Num  := 0;
            elsif X = Size - 1 then
               Byte_Acc := Shift_Left (Byte_Acc, 8 - (Size mod 8));
               Last := Last + 1;
               Result (Last) := Character'Val (Byte_Acc);
               Byte_Acc := 0;
               Bit_Num  := 0;
            end if;
         end loop;
      end loop;
   end Compute;

   task body X_Step is
      Data        : Output;
      Pos         : Natural;
      Y1, Y2      : Natural;
   begin
      accept Compute_Z (Y1, Y2 : Natural) do
         X_Step.Y1 := Y1;
         X_Step.Y2 := Y2;
      end Compute_Z;

      Allocate_Output_Queue (Y1, Y2, Data);
      Compute (Y1, Y2, Data, Pos);

      accept Get_Output (Result : out Output; Last : out Natural) do
         Result := Data;
         Last := Pos;
      end Get_Output;
   end X_Step;

   procedure Allocate_Output_Queue (Y1, Y2 : Natural; Result : out
Output) is
   begin
      Result := new Output_Queue (1 .. (Y2 - Y1 + 8) * Size / 8);
   end Allocate_Output_Queue;


begin
   Size := Positive'Value (Argument (1));
   Two_on_Size := 2.0 / Real (Size);

   Put_Line ("P4");
   Put_Line (Argument (1) & " " & Argument (1));

   declare
      No_Of_Workers : constant := 16;
      Chunk_Size    : constant Positive :=
        (Size + No_Of_Workers) / No_Of_Workers;
      Pool          : array (0 .. No_Of_Workers) of X_Step;
      pragma          Assert (Pool'Length * Chunk_Size >= Size);
      Buffer        : Output;
      Last          : Natural;
   begin
      pragma Assert (Pool'First = 0);

      for P in Pool'Range loop
         Pool (P).Compute_Z
           (Y1 => P * Chunk_Size,
            Y2 => Positive'Min ((P + 1) * Chunk_Size, Size));
      end loop;

      for P in Pool'Range loop
         Pool (P).Get_Output (Buffer, Last);
         Put (Buffer (Buffer'First .. Last));
      end loop;
   end;

end Mandelbrot;



^ permalink raw reply	[relevance 1%]

* Re: Q: Line_IO
  @ 2009-08-31 23:56  2%   ` Georg Bauhaus
  0 siblings, 0 replies; 200+ results
From: Georg Bauhaus @ 2009-08-31 23:56 UTC (permalink / raw)


Dmitry A. Kazakov wrote:

> You could try not to concatenate:
> 
>    Stream_IO.Write (Stdout, To_Bytes (Item));
>    Stream_IO.Write (Stdout, To_Bytes (Separator_Sequence));
> 
> , which should be faster when Item is large.

Yes, though according to some measurements that have been made
in the recent past, "&" is faster for "normal" sized lines.
Other sizes did not produce stable results (on my machine at least).
A test case is in
<4a7bebaa$0$30224$9b4e6d93@newsspool1.arcor-online.net>

However, the two calls are more general, so perhaps they
should replace the concatenation.  And they seem to make
using 'Address be simpler, below---

> Then there is a crazy way to convert congruent types without
> Unchecked_Conversion. I cannot tell whether it is actually faster:

Since 'Address is used for reading anyway, and since, yes,
it is faster, it could replace the unchecked conversion.
Is there a risk with function parameters, not objects of
"better known" storage places?

New version below. If you want to see the difference between
Unchecked_Conversion and 'Address, rename either Print_1 (old)
to Put_Line or Print_2 (new, 'Address) to the same.

> P.S. The superimposed object shall not have initializers.

Does this apply to String parameters?

generic
   Separator_Sequence : in String;  --  ends a line
package Line_IO is

   pragma Elaborate_Body;

   --
   --  High(er) speed reading and writing of lines via Stream I/O.
   --  Made with Unix pipes in mind.
   --
   --  Assumptions:
   --  - Lines are separated by a sequence of characters.
   --  - Characters and stream elements can be used interchangeably.
   --  - Lines are not longer than internal buffer size.
   --
   --  I/O exceptions are propagated

   procedure Put_Line(Item : String);

   function Get_Line return String;

end Line_IO;


with Ada.Streams.Stream_IO;
with Ada.Unchecked_Conversion;

package body Line_IO is

   use Ada.Streams;

   Stdout : Stream_IO.File_Type;
   Stdin : Stream_IO.File_Type;

   -- writing

   procedure Print_1 (Item : String) is

      subtype Index is Stream_Element_Offset range
        Stream_Element_Offset(Item'First)
        .. Stream_Element_Offset(Item'Last + Separator_Sequence'Length);
      subtype XString is String (Item'First
        .. Item'Last + Separator_Sequence'Length);
      subtype XBytes is Stream_Element_Array (Index);
      function To_Bytes is new Ada.Unchecked_Conversion
        (Source => XString,
         Target => XBytes);
   begin
      Stream_IO.Write (Stdout, To_Bytes (Item & Separator_Sequence));
   end Print_1;

   -- Alternative:
   -- - call Stream_IO.Write twice, once for the string, then for the
   --   line separator (terminator)
   -- - specify 'Address, not unchecked_conversion is needed then

   -- We need the separator as a Stream_Element_Array. (Can we
   -- use 'Address on a generic formal object?  If so, then
   -- again, no Unchecked_Conversion is needed (advantage?))

   subtype Sep_String is String(Separator_Sequence'Range);
   subtype Sep_Bytes is Stream_Element_Array
     (Stream_Element_Offset(Separator_Sequence'First)
     .. Stream_Element_Offset(Separator_Sequence'Last));

   function To_Bytes is new Ada.Unchecked_Conversion
     (Source => Sep_String,
      Target => Sep_Bytes);

   Separator_Bytes : constant Stream_Element_Array :=
     To_Bytes(Separator_Sequence);

   procedure Print_2 (Item : String) is
      subtype Index is Stream_Element_Offset range
        Stream_Element_Offset(Item'First)
        .. Stream_Element_Offset(Item'Last);
      subtype XBytes is Stream_Element_Array (Index);
      Item_Bytes: XBytes;
      for Item_Bytes'Address use Item'Address;
   begin
      Stream_IO.Write (Stdout, Item_Bytes);
      Stream_IO.Write (Stdout, Separator_Bytes);
   end Print_2;

   procedure Put_Line (Item : String) renames Print_2;

   -- ----------------
   -- reading
   -- ----------------
   -- Types etc., status variables, and the buffer.  `Buffer` is at the
   -- same time an array of Character and and array of Stream_Element
   -- called `Bytes`.  They share the same address.  This setup makes the
   -- storage at the address either a String (when selecting result
   -- characters) or a Stream_Element_Array (when reading input bytes).

   BUFSIZ: constant := 8_192;
   pragma Assert(Character'Size = Stream_Element'Size);

   SL : constant Natural := Separator_Sequence'Length;

   subtype Extended_Buffer_Index is Positive range 1 .. BUFSIZ + SL;
   subtype Buffer_Index is Extended_Buffer_Index
     range Extended_Buffer_Index'First .. Extended_Buffer_Index'Last - SL;
   subtype Extended_Bytes_Index is Stream_Element_Offset
     range 1 .. Stream_Element_Offset(Extended_Buffer_Index'Last);
   subtype Bytes_Index is Extended_Bytes_Index
     range Extended_Bytes_Index'First
     .. (Extended_Bytes_Index'Last - Stream_Element_Offset(SL));

   subtype Buffer_Data is String(Extended_Buffer_Index);
   subtype Buffer_Bytes is Stream_Element_Array(Extended_Bytes_Index);

   Buffer : Buffer_Data;
   Bytes  : Buffer_Bytes;
   for Bytes'Address use Buffer'Address;

   Position : Natural; -- start of next substring
   Last     : Natural; -- last valid character in buffer


   function Get_Line return String is

      procedure Reload;
      --  move remaining characters to the start of `Buffer` and
      --  fill the following bytes if possible
      --  post: Position in 0 .. 1, and 0 should mean end of file
      --        Last is 0 or else the index of the last valid element in
Buffer

      procedure Reload is
         Remaining : constant Natural := Buffer_Index'Last - Position + 1;
         Last_Index : Stream_Element_Offset;
      begin
         Buffer(1 .. Remaining) := Buffer(Position .. Buffer_Index'Last);

         Stream_IO.Read(Stdin,
           Item => Bytes(Stream_Element_Offset(Remaining) + 1 ..
Bytes_Index'Last),
           Last => Last_Index);
         Last := Natural(Last_Index);
         Buffer(Last + 1 .. Last + SL) := Separator_Sequence;

         Position := Boolean'Pos(Last_Index > 0
           and then Buffer(1) /= ASCII.EOT   -- ^D
           and then Buffer(1) /= ASCII.SUB); -- ^Z

      end Reload;

      function Sep_Index return Natural;
      --  position of next Separator_Sequence
      pragma Inline(Sep_Index);

      function Sep_Index return Natural is
         K : Natural := Position;
      begin
         pragma Assert(K >= Buffer'First);
         pragma Assert(Buffer(Buffer_Index'Last + 1 .. Buffer'Last)
           = Separator_Sequence);

         while Buffer(K) /= Separator_Sequence(1) loop
            K := K + 1;
         end loop;

         return K;
      end Sep_Index;

      Next_Separator : Natural;
   begin  -- Get_Line
      pragma Assert(Position = 0 or else Position in Extended_Buffer_Index);
      pragma Assert(Last = 0 or else Last in Buffer_Index);

      if Position = 0 then
         raise Stream_IO.End_Error;
      end if;

      Next_Separator := Sep_Index;

      if Next_Separator > Buffer_Index'Last then
         -- must be sentinel
         Reload;
         return Get_Line;
      end if;

      if Next_Separator <= Last then
         declare
            Limit : constant Natural := Natural'Max(0, Next_Separator - SL);
            -- there was trouble (Print) when Integer Limit could be
negative
            -- (for 2-char SL and Next_Separator = 1)
            Result : constant String := Buffer(Position .. Limit);
         begin
            Position := Limit + SL + 1;
            return Result;
         end;
      else
         -- the separator is among the characters beyond `Last`
         declare
            Limit : constant Positive := Last;
            Result : constant String := Buffer(Position .. Limit);
         begin
            --  -- makes the spurious line go away
            --  -- But make sure that it isn't cause by Put_Line!
            if Position > Last then
               raise Stream_IO.End_Error;
            end if;
            Position := 0;  -- next call will raise End_Error
            return Result;
         end;
      end if;

      raise Program_Error;
   end Get_Line;


begin
   -- (see <ILmdnWHx29q5VMrZnZ2dnUVZ_sednZ2d@megapath.net> for names
   -- of standard I/O streams when using Janus Ada on Windows.)

   Stream_IO.Open (Stdout,
     Mode => Stream_IO.Out_File,
     Name => "/dev/stdout");
   Stream_IO.Open (Stdin,
     Mode => Stream_IO.In_File,
     Name => "/dev/stdin");

   -- make sure there is no line separator in `Buffer` other than the
sentinel
   Buffer := Buffer_Data'(others => ASCII.NUL);
   Buffer(Buffer_Index'Last + 1 .. Buffer'Last) := Separator_Sequence;
   Position := Buffer_Index'Last + 1;  -- See also
`Getline.Reload.Remaining`
   Last := 0;
end Line_IO;



^ permalink raw reply	[relevance 2%]

* Re: Q: Line_IO
       [not found]     <4a9b045a$0$31875$9b4e6d93@newsspool3.arcor-online.net>
@ 2009-08-31  8:28  0% ` Martin
    1 sibling, 0 replies; 200+ results
From: Martin @ 2009-08-31  8:28 UTC (permalink / raw)


On Aug 30, 11:59 pm, Georg Bauhaus <see.reply...@maps.futureapps.de>
wrote:
> Text_IO seems fairly slow when just reading lines of text.
> Here are two alternative I/O subprograms for Line I/O, in plain Ada,
> based on Stream_IO.   They seem to run significantly faster.
>
> However, there is one glitch and I can't find the cause:
> output always has one more line at the end, an empty one.
> Why?  If you have got a minute to look at this, you will
> also help us with getting faster programs at the Shootout.
> These read lines by the megabyte.
>
> generic
>    Separator_Sequence : in String;  --  ends a line
> package Line_IO is
>
>    pragma Elaborate_Body;
>
>    --
>    --  High(er) speed reading and writing of lines via Stream I/O.
>    --  Made with Unix pipes in mind.
>    --
>    --  Assumptions:
>    --  - Lines are separated by a sequence of characters.
>    --  - Characters and stream elements can be used interchangeably.
>    --  - Lines are not longer than internal buffer size.
>    --
>    --  I/O exceptions are propagated
>
>    procedure Print(Item : String);
>
>    function Getline return String;
>
> end Line_IO;
>
> with Ada.Streams.Stream_IO;
> with Ada.Unchecked_Conversion;
>
> package body Line_IO is
>
>    use Ada.Streams;
>
>    Stdout : Stream_IO.File_Type;
>    Stdin : Stream_IO.File_Type;
>
>    -- writing
>
>    procedure Print (Item : String) is
>
>       subtype Index is Stream_Element_Offset range
>         Stream_Element_Offset(Item'First)
>         .. Stream_Element_Offset(Item'Last + Separator_Sequence'Length);
>       subtype XString is String (Item'First
>         .. Item'Last + Separator_Sequence'Length);
>       subtype XBytes is Stream_Element_Array (Index);
>       function To_Bytes is new Ada.Unchecked_Conversion
>         (Source => XString,
>          Target => XBytes);
>    begin
>       Stream_IO.Write (Stdout, To_Bytes (Item & Separator_Sequence));
>    end Print;
>
>    -- ----------------
>    -- reading
>    -- ----------------
>    -- Types etc., status variables, and the buffer.  `Buffer` is at the
>    -- same time an array of Character and and array of Stream_Element
>    -- called `Bytes`.  They share the same address.  This setup makes the
>    -- storage at the address either a String (when selecting result
>    -- characters) or a Stream_Element_Array (when reading input bytes).
>
>    BUFSIZ: constant := 8_192;
>    pragma Assert(Character'Size = Stream_Element'Size);
>
>    SL : constant Natural := Separator_Sequence'Length;
>
>    subtype Extended_Buffer_Index is Positive range 1 .. BUFSIZ + SL;
>    subtype Buffer_Index is Extended_Buffer_Index
>      range Extended_Buffer_Index'First .. Extended_Buffer_Index'Last - SL;
>    subtype Extended_Bytes_Index is Stream_Element_Offset
>      range 1 .. Stream_Element_Offset(Extended_Buffer_Index'Last);
>    subtype Bytes_Index is Extended_Bytes_Index
>      range Extended_Bytes_Index'First
>      .. (Extended_Bytes_Index'Last - Stream_Element_Offset(SL));
>
>    subtype Buffer_Data is String(Extended_Buffer_Index);
>    subtype Buffer_Bytes is Stream_Element_Array(Extended_Bytes_Index);
>
>    Buffer : Buffer_Data;
>    Bytes  : Buffer_Bytes;
>    for Bytes'Address use Buffer'Address;
>
>    Position : Natural; -- start of next substring
>    Last     : Natural; -- last valid character in buffer
>
>    function Getline return String is
>
>       procedure Reload;
>       --  move remaining characters to the start of `Buffer` and
>       --  fill the following bytes if possible
>       --  post: Position in 0 .. 1, and 0 should mean end of file
>       --        Last is 0 or else the index of the last valid element in
> Buffer
>
>       procedure Reload is
>          Remaining : constant Natural := Buffer_Index'Last - Position + 1;
>          Last_Index : Stream_Element_Offset;
>       begin
>          Buffer(1 .. Remaining) := Buffer(Position .. Buffer_Index'Last);
>
>          Stream_IO.Read(Stdin,
>            Item => Bytes(Stream_Element_Offset(Remaining) + 1 ..
> Bytes_Index'Last),
>                         Last => Last_Index);
>          Last := Natural(Last_Index);
>          Buffer(Last + 1 .. Last + SL) := Separator_Sequence;
>
>          Position := Boolean'Pos(Last_Index > 0
>            and then Buffer(1) /= ASCII.EOT   -- ^D
>            and then Buffer(1) /= ASCII.SUB); -- ^Z
>
>       end Reload;
>
>       function Sep_Index return Natural;
>       --  position of next Separator_Sequence
>       pragma Inline(Sep_Index);
>
>       function Sep_Index return Natural is
>          K : Natural := Position;
>       begin
>          pragma Assert(K >= Buffer'First);
>          pragma Assert(Buffer(Buffer_Index'Last + 1 .. Buffer'Last)
>            = Separator_Sequence);
>
>          while Buffer(K) /= Separator_Sequence(1) loop
>             K := K + 1;
>          end loop;
>
>          return K;
>       end Sep_Index;
>
>       Next_Separator : Natural;
>    begin  -- Getline
>       pragma Assert(Position = 0 or else Position in Extended_Buffer_Index);
>       pragma Assert(Last = 0 or else Last in Buffer_Index);
>
>       if Position = 0 then
>          raise Stream_IO.End_Error;
>       end if;
>
>       Next_Separator := Sep_Index;
>
>       if Next_Separator > Buffer_Index'Last then
>          -- must be sentinel
>          Reload;
>          return Getline;
>       end if;
>
>       if Next_Separator <= Last then
>          declare
>             Limit : constant Natural := Natural'Max(0, Next_Separator - SL);
>             -- there was trouble (Print) when Integer Limit could be
> negative
>             -- (for 2-char SL and Next_Separator = 1)
>             Result : constant String := Buffer(Position .. Limit);
>          begin
>             Position := Limit + SL + 1;
>             return Result;
>          end;
>       else
>          -- the separator is among the characters beyond `Last`
>          declare
>             Limit : constant Positive := Last;
>             Result : constant String := Buffer(Position .. Limit);
>          begin
>             Position := 0;  -- next call will raise End_Error
>             return Result;
>          end;
>       end if;
>
>       raise Program_Error;
>    end Getline;
>
> begin
>    -- (see <ILmdnWHx29q5VMrZnZ2dnUVZ_sedn...@megapath.net> for names
>    -- of standard I/O streams when using Janus Ada on Windows.)
>
>    Stream_IO.Open (Stdout,
>      Mode => Stream_IO.Out_File,
>      Name => "/dev/stdout");
>    Stream_IO.Open (Stdin,
>      Mode => Stream_IO.In_File,
>      Name => "/dev/stdin");
>
>    -- make sure there is no line separator in `Buffer` other than the
> sentinel
>    Buffer := Buffer_Data'(others => ASCII.NUL);
>    Buffer(Buffer_Index'Last + 1 .. Buffer'Last) := Separator_Sequence;
>    Position := Buffer_Index'Last + 1;  -- See also
> `Getline.Reload.Remaining`
>    Last := 0;
> end Line_IO;
>
> --
> -- A small test program.
> --
> with Line_IO;
> with Ada.Text_IO;
>
> procedure Test_Line_IO is
>    Want_Text_IO : constant Boolean := False;
>
>    -- pick the correct one for your input files
>    UnixLF  : constant String := String'(1 => ASCII.LF);
>    MacCR   : constant String := String'(1 => ASCII.CR);
>    OS2CRLF : constant String := String'(1 => ASCII.CR, 2 => ASCII.LF);
>
>    package LIO is new Line_IO(Separator_Sequence => UnixLF);
>
> begin
>    if Want_Text_IO then
>       loop
>          declare
>             A_Line : constant String := Ada.Text_IO.Get_Line;
>          begin
>             LIO.Print(A_Line);
>             null;
>             pragma Inspection_Point(A_Line);
>          end;
>       end loop;
>    else
>       loop
>          declare
>             A_Line : constant String := LIO.Getline;
>          begin
>             LIO.Print(A_Line);
>             null;
>             pragma Inspection_Point(A_Line);
>          end;
>       end loop;
>    end if;
>
> end Test_Line_IO;

Nice one...I'll try these out on Win23 and see what happens :-)

But surely "Put_Line" and "Get_Line" are preferable subprogram
names?...

Cheers
-- Martin



^ permalink raw reply	[relevance 0%]

* Re: Ada Shootout program for K-Nucleotide (patches)
  @ 2009-08-07  8:53  2%                                   ` Georg Bauhaus
  0 siblings, 0 replies; 200+ results
From: Georg Bauhaus @ 2009-08-07  8:53 UTC (permalink / raw)


Jeffrey R. Carter wrote:

> How about
> 
> subtype Index is Stream_Element_Offset range
>    Stream_Element_Offset(Item'First) .. Stream_Element_Offset(Item'Last
> + 1);
> subtype XString is String (Item'First .. Item'Last + 1);
> 
> followed by
> 
> Stream_IO.Write (stdout, To_Bytes (Item & ASCII.LF) );

Shorter, and consistently faster when strings are short (10:11).
I'll add this.

I don't know, though, whether or not exchanging one  "&" for
one less Stream_IO.Write is also good when strings are larger,
because of the copying in "&", CPU cache sizes, ...
The test results I get from the program below vary a lot
for anything but the short string (1..70) variant.

Since the test has been run in a VM on top of Vista, I don't
trust the timings that much anyway.  Maybe the order
of tests has an effect, too?  Does somebody have a stable
Linux (or Unix) test environment?  Could you try this?


package Print_Pak is

   procedure Print_Old (Item : String);

   procedure Print (Item : String);

end Print_Pak;


with Ada.Real_Time;  use Ada.Real_Time;
with Print_Pak;

procedure Test_Print is

   type String_Kind is (Short_Strings,
                        Medium_Strings,
                        Long_Strings);
   type String_Access is access String;
   type Run is record
      Data : String_Access;
      Rounds : Positive;
   end record;

   Test_Size : constant := 50_000_000;
   Max_Run : constant array (String_Kind) of Run :=
     (Short_Strings =>
        (Data => new String(1 .. 70 * 1),
         Rounds => Test_Size / 1),
      Medium_Strings =>
        (Data => new String(1 .. 70 * 100),
         Rounds => Test_Size / 100),
      Long_Strings =>
        (Data => new String(1 .. 70 * 10_000),
         Rounds => Test_Size / 10_000));

   Start, Stop: array (String_Kind) of Time;

   procedure Terminal (Message : String) is separate;

begin

   Old: for Kind in Short_Strings .. Long_Strings loop

      Start(Kind) := Clock;
      for K in 1 .. Max_Run(Kind).Rounds loop
         Print_Pak.Print_Old (Max_Run(Kind).Data.all);
      end loop;
      Stop(Kind) := Clock;

      Terminal ("Print_Old, "
                  & String_Kind'Image(Kind)
                  & ": "
                  & Duration'Image (To_Duration (Stop(Kind)
                                                   - Start(Kind))));
   end loop Old;

   for Kind in Short_Strings .. Long_Strings loop

      Start(Kind) := Clock;
      for K in 1 .. Max_Run(Kind).Rounds loop
         Print_Pak.Print (Max_Run(Kind).Data.all);
      end loop;
      Stop(Kind) := Clock;

      Terminal ("Print, "
                  & String_Kind'Image(Kind)
                  & ": "
                  & Duration'Image (To_Duration (Stop(Kind)
                                                   - Start(Kind))));
   end loop;


end Test_Print;


with Ada.Text_IO;

separate (Test_Print)
procedure Terminal (Message : String) is
begin
   Ada.Text_IO.Put_Line(Ada.Text_IO.Current_Error, Message);
end Terminal;


with Ada.Streams.Stream_IO;  use Ada.Streams;
with Unchecked_Conversion;

package body Print_Pak is

    function To_Byte is new Unchecked_Conversion
     (Source => Character,
      Target => Stream_Element);

   stdout : Stream_IO.File_Type;

   procedure Print_Old (Item : String) is
      subtype Index is Stream_Element_Offset range
        Stream_Element_Offset(Item'First) ..
Stream_Element_Offset(Item'Last);
      subtype XString is String (Item'Range);
      subtype XBytes is Stream_Element_Array (Index);
      function To_Bytes is new Unchecked_Conversion
        (Source => XString,
         Target => XBytes);
      LF : constant Stream_Element_Array := (1 => To_Byte (ASCII.LF));
   begin
      Stream_IO.Write (stdout, To_Bytes (Item));
      Stream_IO.Write (stdout, LF);
   end Print_Old;

   procedure Print (Item : String) is
      subtype Index is Stream_Element_Offset range
        Stream_Element_Offset(Item'First)
        .. Stream_Element_Offset(Item'Last + 1);
      subtype XString is String (Item'First .. Item'Last + 1);
      subtype XBytes is Stream_Element_Array (Index);
      function To_Bytes is new Unchecked_Conversion
        (Source => XString,
         Target => XBytes);
   begin
      Stream_IO.Write (stdout, To_Bytes (Item & ASCII.LF));
   end Print;

begin
   Stream_IO.Open (stdout,
                   Mode => Stream_IO.Out_File,
                   Name => "/dev/stdout");
end Print_Pak;



^ permalink raw reply	[relevance 2%]

* Re: Alternatives to C: ObjectPascal, Eiffel, Ada or Modula-3?
  @ 2009-07-21  7:54  3%             ` Ludovic Brenta
  0 siblings, 0 replies; 200+ results
From: Ludovic Brenta @ 2009-07-21  7:54 UTC (permalink / raw)


On Jul 21, 3:33 am, Cesar Rabak <csra...@yahoo.com.br> wrote:
> Ludovic Brenta escreveu:
>
>
>
> > Cesar Rabak wrote on comp.lang.eiffel, comp.lang.ada:
> >> Nicholas Paul Collin Gloucester escreveu:
> > [...]
> >>> In this case there is a reason for having more types. An angle and a
> >>> length are simply not interchangable, so they should not be
> >>> represented both by Float. The amount of money equal to U.S.$1.00 is
> >>> not equal to the amount of money equal to 1.00 Canadian dollar, but
> >>> they are both written with the number 1.00.
> >> I disagree strongly: an angle in radians is a real number as any other
> >> there is not any intrinsic difference in its *type* on ordinary
> >> Mathematics.  Dimensionally they are 'pure numbers' with no unit
> >> atached, your example on monetary units being fallacious, so non
> >> sequitur.
>
> > Ada is not a language for mathematicians (mathematicians would rather
> > use e.g. Octave), it is a language for engineers.  In engineering,
> > there are very few pure numbers and quite a lot of dimensioned
> > numbers.  As an engineer, I certainly view angles, frequencies and
> > dimensionless constants (e.g. correction factors) as all having
> > different dimensions.
>
> Nice you bring this, Ludovic! However, remember the OP question:
> <quote>
> I'm a CS student and I often need to write number-crunching code dealing
> with combinatorial optimization problems.
> What I do usually is implementing ad-hoc algorithms and testing their
> performance against other previously-known solutions, including general
> solvers.
> </quote>
>
> So your suggestion is to steer from Ada?

No, I would personally use Ada and make the number-crunching code into
generic units.  The user would then provide their application-defined
floating-point type as a generic parameter to instantiate the code.

> > I would have declared the types for angles thus:
> > type Radians is new Float; -- no range restriction
>
> > You focused too much, IMHO, on the range restriction which is not the
> > important part.  The important part is that, in Ada, this declares a
> > new *type* (not a "subtype" or "nickname for Float"), which is
> > *incompatible* with Float or any other type.  
>
> More or less. It has all the operations of the derived type, uses the
> same representation on the machine.  The incompatibility is syntactic no
> in its essence.
>
> For example: which type is the operation X^2 + Y^2, or Magnitude *
> cos(Theta)?

Simple.  In Ada, these expressions are illegal.  The user must
explicitly convert some of the values to a compatible type before
being allowed to mix objects of different types, e.g.

X : Horizontal_Coordinate := ...;
Y : Vertical_Coordinate := ...
R : Magnitude := Magnitude (X)**2 + Magnitude (Y)**2;
X := Horizontal_Coordinate (R) * Magnitude (cos (Theta));

You may say is it not "ergonomic" but, as an engineer, I see this as
"saying what you mean".  The best approach, of course, is to make the
above operations into application-specific operators, e.g.

function Magnitude_Of (X : Horizontal_Coordinate; Y :
Vertical_Coordinate)
  return Magnitude;

> Does the subtyping in Ada complain if one makes an operation on two
> variables of type Length (here defined as 'type Length is new Float;')
> that there is not a compatible Length squared defined?

No, unfortunately.  In Ada, Length squared is a Length.  There are
however libraries like [1] that allow full dimensioned computations.
They use compile-time checks where possible and run-time checks where
necessary.

[1] http://www.dmitry-kazakov.de/ada/units.htm

> > This incompatibility has
> > two benefits: early detection of some errors (except, of course, those
> > involving literals of type universal_real) and documentation, to the
> > human reader, of what objects of the type represent in the real world.
>
> I agree this allows for some error protection, but as I showed already
> this only happens *after* the variable has been initialized with a value
> which for non trivial programs have to come from outside world.

No.  The incompatibility between types is checked at compile time and
does not depend on values.  Indeed, it still works if all types are
declared as "new Float" with no range restriction.

> > [...]
> >>> Nothing is foolproof, but I did prevent some accidents.
> >> Yes, I agree on that and Ada has been a step forward on this direction,
> >> but as has been written elsewhere in this thread, Ada types do not form
> >> a 'type system' so it brings moderate safety against errors.
>
> > In Ada, floating-point literals (which were the crux of your argument)
> > belong to the type universal_real which allows implicit conversion to
> > any floating-point type.  If I understand your argument correctly, you
> > are suggesting that universal_real (and universal_integer) should
> > disappear and that the language should force the programmer to qualify
> > every literal, i.e.:
>
> > X : Radians := Radians'(3.0);
>
> Why? Doesn't it make sense for you?
>
> How would Ada gurus suggest the interfaces for reading data from outside
> the program (GUI, command line parameters, fields in files, etc.) be
> coded (in order to make full use of Ada features)?

The interfaces for reading from the outside already exist and they all
use typed input-output routines which check for range constraints (if
applicable) at run time. This makes is simply impossible to create
untyped values, or values of type universal_real, from outside the
program source. One example with streams:

   type Radians is new Float;
   F : Ada.Streams.Stream_IO.File_Type;
begin
   Ada.Streams.Stream_IO.Open (File => F,
                               Mode => Ada.Streams.Stream_IO.In_File,
                               Name => "foo.dat");
   declare
      S : constant Ada.Streams.Stream_IO.Stream_Access :=
        Ada.Streams.Stream_IO.Stream (F);
      R : Radians;
   begin
      Radians'Read (Stream => S, Item => R);
   end;
end;

(note : I wrote the above in an extra-verbose style to make context
unnecessary).

--
Ludovic Brenta.



^ permalink raw reply	[relevance 3%]

* Re: Load an object from a file
  @ 2009-04-09 21:22  3%     ` Ludovic Brenta
  0 siblings, 0 replies; 200+ results
From: Ludovic Brenta @ 2009-04-09 21:22 UTC (permalink / raw)


On Apr 9, 10:32 pm, Olivier Scalbert <olivier.scalb...@algosyn.com>
wrote:
> Hi,
>
> I still have one question ...
> How can I implement the Load_Class procedure that will use the Input
> function?
> I do not know how to get the needed stream from a given file name.
> And I do not know how to define the Class_File_Structure result (I get
> an unconstrained subtype (need initialization)).
[...]
> package body jvm is
[...]
>      procedure Load_Class(File_Name: String) is
>
>          Class_File_Structure: Class_File_Structure_T; -- (unconstrained
> subtype (need initialization)
>      begin
>          Put_Line(File_Name);
>
>          Class_file_Structure := Input(Stream ???);
>
>      end Load_Class;
[...]
> end jvm;

Because Class_File_Structure_T is unconstrained and needs
initialization, you cannot use a procedure to load one: out parameters
don't work, and the procedure cannot write into a variable because you
can't declare a variable without initializing it.  So, here is a
possible solution replacing your procedure with a function:

with Ada.Streams.Stream_IO;
...
function From_File (File_Name : String) return Class_File_Structure_T
is
   File : Ada.Streams.Stream_IO.File_Type;
begin
   Ada.Streams.Stream_IO.Open (File,
                               File_Mode =>
Ada.Streams.Stream_IO.In_File,
                               Name      => File_Name);
   declare
      Result : constant Class_File_Structure_T :=
        Class_File_Structure_T'Input (Ada.Streams.Stream_IO.Stream
(File));
   begin
      Ada.Streams.Stream_IO.Close (File);
      return Result;
   end;
end From_File;

HTH

--
Ludovic Brenta.



^ permalink raw reply	[relevance 3%]

* Re: Ada.Directories problems, a summary
  2009-01-02 14:22  0%     ` Ivan Levashew
@ 2009-01-02 14:49  0%       ` Dmitry A. Kazakov
  0 siblings, 0 replies; 200+ results
From: Dmitry A. Kazakov @ 2009-01-02 14:49 UTC (permalink / raw)


On Fri, 2 Jan 2009 06:22:14 -0800 (PST), Ivan Levashew wrote:

> Dmitry A. Kazakov wrote:
>>
>> I don't see any problem with that. Ada.Streams.Stream_IO should do it.
> 
> I was thinking Modula-2's text API vs. Ada's one. Both
> are advanced, but I can hardly remember when was the last
> time I needed Ada's Page, Set_Line, etc. stuff.

I don't see your point.
 
>>> which is stored in a zip file,
>>> which itself is hosted on an FTP server,
>>> which is being accessed through a SOCKS5 proxy,
>>> which is being accessed through an HTTPS proxy (CONNECT method),
>>> which is being accessed directly.
>>
>> All these are just not files. It is a UNIX-world aberration that everything
>> must be a file. Everything is nothing.
>
> I don't care about UNIX convention. There are abstraction like
> "sequence of octets", "ability to establish connection with",
> etc., and I'd like to deal with these abstractions and not with
> what particular cases OS designers gave me instead.

But directories have nothing to do with streams of octets. It is
Ada.Streams' business?
 
>>> Every part of Ada RTL and GNAT RTL is locked down to immediate
>>> filesystem/immediate network connectivity.
>>
>> Which is good, because your list has no end. What about CORBA, DB
>> connections etc?

> The point isn't about CORBA and FTP. The point is about
> indirection. As soon as one has libraries for FTP/ZIP/SOCKS5,
> one should have opportunity to do what I've said.

There are millions of libraries. I really don't see your point. Further
there is nothing in common in FTP/ZIP/SOCKS5.

If this is about providing an octet stream interface to everything in the
world, then it is a reincarnation of the old UNIX's stupidity "everyting is
a file."  In software design this sort of stupidity is called abstraction
inversion.

> Currently, Ada RTL is designed in a way that one has to write
> text API implementation from scratch.

I don't know what you understand under "text API implementation."

>> The option is to limit it to files.

> A programming language of software engineers shouldn't
> have stupid limitations like this.

First you said that this were impossible. I don't find stupid limiting
portable Ada.Directories to files. Stupid were to have OS-dependent
interface of. Presently it has, which is a problem.

Ada may have a lot of weaknesses, but it is unbeatable when you need to
write a portable application.
 
>> Later on URI schemes could added in a set of separate
>> packages and so on.
> 
> URI scheme parser is not a major part. URI is bad for accessing
> multivolume archives, cryptography-enabled SFTPs and so on.

Yes, this is what I meant.

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



^ permalink raw reply	[relevance 0%]

* Re: Ada.Directories problems, a summary
  2009-01-01 14:15  1%   ` Dmitry A. Kazakov
@ 2009-01-02 14:22  0%     ` Ivan Levashew
  2009-01-02 14:49  0%       ` Dmitry A. Kazakov
  0 siblings, 1 reply; 200+ results
From: Ivan Levashew @ 2009-01-02 14:22 UTC (permalink / raw)


Dmitry A. Kazakov wrote:
>
> > Ada RTL isn't enough (and wasn't ever) to do anything serious.
>
> I hope running Ada programs qualifies as serious. (:-))
>
Serious Ada programs use big amount of non-RTL libraries.

>
> Nope, Ada RTL must support design of platform-independent applications. Any
> OS-specific library has no use in my eyes. I think there is a broad
> understanding of this beyond Ada community.

I was talking about OS-specific implementation. Existence of
fallback implementation makes library 100% portable.

> As an example consider GTK
> introducing GIO library which tries to abstract the I/O OS layer.

Yes, I meant something like this (more precisely, I had NSPR
in mind).

> > Read word by word a file,
>
> I don't see any problem with that. Ada.Streams.Stream_IO should do it.

I was thinking Modula-2's text API vs. Ada's one. Both
are advanced, but I can hardly remember when was the last
time I needed Ada's Page, Set_Line, etc. stuff.

> > which is stored in a zip file,
> > which itself is hosted on an FTP server,
> > which is being accessed through a SOCKS5 proxy,
> > which is being accessed through an HTTPS proxy (CONNECT method),
> > which is being accessed directly.
>
> All these are just not files. It is a UNIX-world aberration that everything
> must be a file. Everything is nothing.
I don't care about UNIX convention. There are abstraction like
"sequence of octets", "ability to establish connection with",
etc., and I'd like to deal with these abstractions and not with
what particular cases OS designers gave me instead.

> > Every part of Ada RTL and GNAT RTL is locked down to immediate
> > filesystem/immediate network connectivity.
>
> Which is good, because your list has no end. What about CORBA, DB
> connections etc?
The point isn't about CORBA and FTP. The point is about
indirection. As soon as one has libraries for FTP/ZIP/SOCKS5,
one should have opportunity to do what I've said.

Currently, Ada RTL is designed in a way that one has to write
text API implementation from scratch.

> The option is to limit it to files.
A programming language of software engineers shouldn't
have stupid limitations like this.

> Later on URI schemes could added in a set of separate
> packages and so on.

URI scheme parser is not a major part. URI is bad for accessing
multivolume archives, cryptography-enabled SFTPs and so on.




^ permalink raw reply	[relevance 0%]

* Re: Ada.Directories problems, a summary
  @ 2009-01-01 14:15  1%   ` Dmitry A. Kazakov
  2009-01-02 14:22  0%     ` Ivan Levashew
  0 siblings, 1 reply; 200+ results
From: Dmitry A. Kazakov @ 2009-01-01 14:15 UTC (permalink / raw)


On Thu, 1 Jan 2009 05:47:13 -0800 (PST), Ivan Levashew wrote:

> Dmitry A. Kazakov wrote:
> 
>> After experimenting with Ada.Directories I collected the issues I think
>> must be addressed to make Ada.Directories more usable:
> 
> Ada RTL isn't enough (and wasn't ever) to do anything serious.

I hope running Ada programs qualifies as serious. (:-))

> I think a replacement library should be designed, with
> OS-specific and fallback (relying on Ada RTL) implementations.

Nope, Ada RTL must support design of platform-independent applications. Any
OS-specific library has no use in my eyes. I think there is a broad
understanding of this beyond Ada community. As an example consider GTK
introducing GIO library which tries to abstract the I/O OS layer. [GIO does
not work, but that is another story...]

> Your problems are not the only ones. For example, with Ada and
> GNAT RTL, I can't easily:
> Read word by word a file,

I don't see any problem with that. Ada.Streams.Stream_IO should do it.

> which is stored in a zip file,
> which itself is hosted on an FTP server,
> which is being accessed through a SOCKS5 proxy,
> which is being accessed through an HTTPS proxy (CONNECT method),
> which is being accessed directly.

All these are just not files. It is a UNIX-world aberration that everything
must be a file. Everything is nothing.

> Every part of Ada RTL and GNAT RTL is locked down to immediate
> filesystem/immediate network connectivity.

Which is good, because your list has no end. What about CORBA, DB
connections etc?

> I can't see any option other than another library.

The option is to limit it to files. Later on URI schemes could added in a
set of separate packages and so on.

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



^ permalink raw reply	[relevance 1%]

* Re: Controlling endian-ness? (Example: Attribute Overriding)
  @ 2008-08-06 17:07  3%     ` anon
  0 siblings, 0 replies; 200+ results
From: anon @ 2008-08-06 17:07 UTC (permalink / raw)


--  File: newprog.adb
--
-- An example of how to Override an built-in Attribute:
-- Based on examples from RM 13.3 ( 84 ) and 13.13.2 ( 40 ) ;
--
with Interfaces ;
use  Interfaces ;

with Ada.Text_IO ;
use  Ada.Text_IO ;

with Ada.Streams.Stream_IO;

procedure NewProg is

  -----------------------------------------------------------

   type Unsigned_32 is new Interfaces.Unsigned_32 ; 

  --
  -- Define New Attribute Specifications
  --
   procedure newWrite
     ( Stream : access Ada.Streams.Root_Stream_Type'Class;
       Item   : in Unsigned_32 ) ;
                                           -- Performs Overriding of attribute
    for Unsigned_32'Write use newWrite ; 

  -----------------------------------------------------------

  --
  -- Define New Attribute Body
  --
   procedure newWrite
     ( Stream : access Ada.Streams.Root_Stream_Type'Class;
       Item   : in Unsigned_32 ) is
     begin
       --
       -- Replace with your "Write code"
       --
       -- test message only, just to prove that we are using this Attribute 
       --
       Put_Line ( "New Write Attribute" ) ; 
     end newWrite ;

  -----------------------------------------------------------

   Data_File      : Ada.Streams.Stream_IO.File_Type;
   Data_Stream    : Ada.Streams.Stream_IO.Stream_Access;
   The_Filename   : constant String :=  "Test.Dat" ;

  Test_Data : Unsigned_32 := 9 ;

begin

  Ada.Streams.Stream_IO.Create ( Data_File, 
                                 Ada.Streams.Stream_IO.Out_File,
                                 The_Filename ) ;

  Data_Stream := Ada.Streams.Stream_IO.Stream ( Data_File ) ;


  Put_Line ( "Testing: New Atrribute: Write" ) ;
  New_Line ;

  Unsigned_32'Write ( Data_Stream, Test_Data ) ;

  Ada.Streams.Stream_IO.Close ( Data_File ) ;

end NewProg ;

In <4898d0ca$0$19680$4d3efbfe@news.sover.net>, "Peter C. Chapin" <pcc482719@gmail.com> writes:
>anon wrote:
>
>> For using Unsigned_32. Why not just override the built-in Write attributes 
>> routines for Unsigned_32 by re-writing the attributes routines. This may at 
>> most require a new package with a few extra attributes routines that may 
>> be needed. Also, this will also allow you to use "Shift_Left/Shift_Right" 
>> directly with Unsigned_32.  
>> 
>> So in your program you could use:
>> 
>>    Data : Unsigned_32 ;
>>   ...
>>    Unsigned_32'Write ( Stream_Pointer, Data ) ;
>
>I actually tried something like this but the compiler told me that I 
>couldn't redefine attributes for that type (or something like that). I 
>think the problem is that since the type is defined in another package 
>it is already frozen or some such. It could also be that I did it wrong.
>
>Peter




^ permalink raw reply	[relevance 3%]

* Re: Controlling endian-ness?
  2008-08-05  2:16  2% Controlling endian-ness? Peter C. Chapin
  2008-08-05  3:10  0% ` Steve
@ 2008-08-05 14:59  0% ` anon
    1 sibling, 1 reply; 200+ results
From: anon @ 2008-08-05 14:59 UTC (permalink / raw)


For using Unsigned_32. Why not just override the built-in Write attributes 
routines for Unsigned_32 by re-writing the attributes routines. This may at 
most require a new package with a few extra attributes routines that may 
be needed. Also, this will also allow you to use "Shift_Left/Shift_Right" 
directly with Unsigned_32.  

So in your program you could use:

   Data : Unsigned_32 ;
  ...
   Unsigned_32'Write ( Stream_Pointer, Data ) ;


In GNAT you can not add new attributes, but you can override the built-in 
versions with a new set of attributes routines. 



In <4897b7f5$0$19705$4d3efbfe@news.sover.net>, "Peter C. Chapin" <pcc482719@gmail.com> writes:
>I'm trying to read/write 32 bit quantities from/to a binary file. The 
>file has a format defined by a specification that is outside my control. 
>Some of the quantities are stored in the file in big endian order. 
>However, my machine is a little endian machine. The file in question 
>also contains various values that are most naturally represented with 
>different data types. Thus I'm looking at Stream_IO as a way to deal 
>with it.
>
>As an experiment I wrote a small program that defines a 32 bit unsigned 
>integer type and then overrides the 'Write attribute to write the value 
>in big endian form. Here is what I have:
>
>with Ada.Streams;              use Ada.Streams;
>with Ada.Streams.Stream_IO;    use Ada.Streams.Stream_IO;
>with Interfaces;               use Interfaces;
>
>procedure Stream_Check is
>    pragma Assert(Stream_Element'Size = 8);
>
>    type Word is mod 2**32;
>    procedure Word_Write
>      (Stream : access Root_Stream_Type'Class; Item : in Word);
>    for Word'Size  use 32;
>    for Word'Write use Word_Write;
>
>    procedure Word_Write
>      (Stream : access Root_Stream_Type'Class; Item : in Word) is
>       Buffer    : Stream_Element_Array(0..3);
>       Workspace : Unsigned_32 := Unsigned_32(Word);  -- ERROR HERE!
>    begin
>       Buffer(0) :=
>           Stream_Element(Shift_Right((Workspace and 16#FF000000#), 24));
>       Buffer(1) :=
>           Stream_Element(Shift_Right((Workspace and 16#00FF0000#), 16));
>       Buffer(2) :=
>           Stream_Element(Shift_Right((Workspace and 16#0000FF00#),  8));
>       Buffer(3) :=
>           Stream_Element(Shift_Right((Workspace and 16#000000FF#),  0));
>       Write(Stream.all, Buffer);
>    end Word_Write;
>
>    Output_File    : File_Type;
>    Stream_Pointer : Stream_Access;
>
>    W : Word := 16#0000FFFF#;
>begin
>    Create(Output_File, Out_File, "test.bin");
>    Stream_Pointer := Stream(Output_File);
>    Word'Write(Stream_Pointer, W);
>    Close(Output_File);
>end Stream_Check;
>
>I'm using GNAT GPL 2008. It produces an error on the indicated line 
>saying, "invalid use of subtype mark in expression or call." Apparently 
>it doesn't like me trying to convert a Word to an Unsigned_32, but I 
>don't understand why (am I doing that conversion right?).
>
>I want to use Unsigned_32 so that I can use Shift_Right. I can't 
>override the 'Write attribute for Unsigned_32 directly because it's in a 
>different package (right?).
>
>Overall I have a feeling that there is probably a much better way to do 
>this.
>
>Peter




^ permalink raw reply	[relevance 0%]

* Re: Controlling endian-ness?
  2008-08-05  2:16  2% Controlling endian-ness? Peter C. Chapin
@ 2008-08-05  3:10  0% ` Steve
  2008-08-05 14:59  0% ` anon
  1 sibling, 0 replies; 200+ results
From: Steve @ 2008-08-05  3:10 UTC (permalink / raw)


"Peter C. Chapin" <pcc482719@gmail.com> wrote in message 
news:4897b7f5$0$19705$4d3efbfe@news.sover.net...
> I'm trying to read/write 32 bit quantities from/to a binary file. The file 
> has a format defined by a specification that is outside my control. Some 
> of the quantities are stored in the file in big endian order. However, my 
> machine is a little endian machine. The file in question also contains 
> various values that are most naturally represented with different data 
> types. Thus I'm looking at Stream_IO as a way to deal with it.
>
> As an experiment I wrote a small program that defines a 32 bit unsigned 
> integer type and then overrides the 'Write attribute to write the value in 
> big endian form. Here is what I have:
>
> with Ada.Streams;              use Ada.Streams;
> with Ada.Streams.Stream_IO;    use Ada.Streams.Stream_IO;
> with Interfaces;               use Interfaces;
>
> procedure Stream_Check is
>    pragma Assert(Stream_Element'Size = 8);
>
>    type Word is mod 2**32;
>    procedure Word_Write
>      (Stream : access Root_Stream_Type'Class; Item : in Word);
>    for Word'Size  use 32;
>    for Word'Write use Word_Write;
>
>    procedure Word_Write
>      (Stream : access Root_Stream_Type'Class; Item : in Word) is
>       Buffer    : Stream_Element_Array(0..3);
>       Workspace : Unsigned_32 := Unsigned_32(Word);  -- ERROR HERE!
>    begin
>       Buffer(0) :=
>           Stream_Element(Shift_Right((Workspace and 16#FF000000#), 24));
>       Buffer(1) :=
>           Stream_Element(Shift_Right((Workspace and 16#00FF0000#), 16));
>       Buffer(2) :=
>           Stream_Element(Shift_Right((Workspace and 16#0000FF00#),  8));
>       Buffer(3) :=
>           Stream_Element(Shift_Right((Workspace and 16#000000FF#),  0));
>       Write(Stream.all, Buffer);
>    end Word_Write;
>
>    Output_File    : File_Type;
>    Stream_Pointer : Stream_Access;
>
>    W : Word := 16#0000FFFF#;
> begin
>    Create(Output_File, Out_File, "test.bin");
>    Stream_Pointer := Stream(Output_File);
>    Word'Write(Stream_Pointer, W);
>    Close(Output_File);
> end Stream_Check;
>
> I'm using GNAT GPL 2008. It produces an error on the indicated line 
> saying, "invalid use of subtype mark in expression or call." Apparently it 
> doesn't like me trying to convert a Word to an Unsigned_32, but I don't 
> understand why (am I doing that conversion right?).
>
> I want to use Unsigned_32 so that I can use Shift_Right. I can't override 
> the 'Write attribute for Unsigned_32 directly because it's in a different 
> package (right?).
>
> Overall I have a feeling that there is probably a much better way to do 
> this.
>
> Peter

I don't know if this will be useful to you, but here is the technique I used 
for reversing the byte order on a 32 bit integer.  Actually I was going for 
"network byte order" of a float (s_float is a 32 bit float, u_long is a 
32bit unsigned integer).

      TYPE aByte IS MOD 256;
      FOR aByte'SIZE USE 8;
      TYPE aByteArray IS ARRAY( Positive RANGE <> ) OF aByte;

      FUNCTION nltohf( value : u_long ) RETURN s_float IS
         TYPE aFourBytes IS NEW aByteArray(1..4);
         FUNCTION Conv IS
           NEW Ada.Unchecked_Conversion( aFourBytes, s_float );
         FUNCTION Conv IS
           NEW Ada.Unchecked_Conversion( u_long, aFourBytes );
         temp : aFourBytes := Conv( value );
      BEGIN
         RETURN Conv( aFourBytes'( temp(4), temp(3), temp(2), temp(1) ) );
      END nltohf;

It isn't endian neutral (or particularly pretty), but it got the job done.

Regards,
Steve







^ permalink raw reply	[relevance 0%]

* Controlling endian-ness?
@ 2008-08-05  2:16  2% Peter C. Chapin
  2008-08-05  3:10  0% ` Steve
  2008-08-05 14:59  0% ` anon
  0 siblings, 2 replies; 200+ results
From: Peter C. Chapin @ 2008-08-05  2:16 UTC (permalink / raw)


I'm trying to read/write 32 bit quantities from/to a binary file. The 
file has a format defined by a specification that is outside my control. 
Some of the quantities are stored in the file in big endian order. 
However, my machine is a little endian machine. The file in question 
also contains various values that are most naturally represented with 
different data types. Thus I'm looking at Stream_IO as a way to deal 
with it.

As an experiment I wrote a small program that defines a 32 bit unsigned 
integer type and then overrides the 'Write attribute to write the value 
in big endian form. Here is what I have:

with Ada.Streams;              use Ada.Streams;
with Ada.Streams.Stream_IO;    use Ada.Streams.Stream_IO;
with Interfaces;               use Interfaces;

procedure Stream_Check is
    pragma Assert(Stream_Element'Size = 8);

    type Word is mod 2**32;
    procedure Word_Write
      (Stream : access Root_Stream_Type'Class; Item : in Word);
    for Word'Size  use 32;
    for Word'Write use Word_Write;

    procedure Word_Write
      (Stream : access Root_Stream_Type'Class; Item : in Word) is
       Buffer    : Stream_Element_Array(0..3);
       Workspace : Unsigned_32 := Unsigned_32(Word);  -- ERROR HERE!
    begin
       Buffer(0) :=
           Stream_Element(Shift_Right((Workspace and 16#FF000000#), 24));
       Buffer(1) :=
           Stream_Element(Shift_Right((Workspace and 16#00FF0000#), 16));
       Buffer(2) :=
           Stream_Element(Shift_Right((Workspace and 16#0000FF00#),  8));
       Buffer(3) :=
           Stream_Element(Shift_Right((Workspace and 16#000000FF#),  0));
       Write(Stream.all, Buffer);
    end Word_Write;

    Output_File    : File_Type;
    Stream_Pointer : Stream_Access;

    W : Word := 16#0000FFFF#;
begin
    Create(Output_File, Out_File, "test.bin");
    Stream_Pointer := Stream(Output_File);
    Word'Write(Stream_Pointer, W);
    Close(Output_File);
end Stream_Check;

I'm using GNAT GPL 2008. It produces an error on the indicated line 
saying, "invalid use of subtype mark in expression or call." Apparently 
it doesn't like me trying to convert a Word to an Unsigned_32, but I 
don't understand why (am I doing that conversion right?).

I want to use Unsigned_32 so that I can use Shift_Right. I can't 
override the 'Write attribute for Unsigned_32 directly because it's in a 
different package (right?).

Overall I have a feeling that there is probably a much better way to do 
this.

Peter



^ permalink raw reply	[relevance 2%]

* Re: Mixing reading and writing to a text file
  2007-08-03  1:26  2% ` Randy Brukardt
@ 2007-08-06  7:35  2%   ` msimonides
  0 siblings, 0 replies; 200+ results
From: msimonides @ 2007-08-06  7:35 UTC (permalink / raw)


On 3 Sie, 03:26, "Randy Brukardt" <ra...@rrsoftware.com> wrote:
> <msimoni...@power.com.pl> wrote in message
[...]
> > The problem I have is with writing the state information back to file.
> > Ada.Text_IO and Ada.Streams.Stream_IO only allow opening file for
> > input or for output. In the latter case the file is being truncated
> > (as far as I understand the ARM).
>
> The ARM was screwed up in Ada 95 vis-a-vis Ada.Streams.Stream_IO. This was
> fixed in the Amendment (and the fix is supposed to apply to Ada 95 compilers
> as well). Specifically, stream files are *not* truncated when they are
> opened for output (otherwise it would be virtually impossible to use the
> positioning functions to write a stream file).
>
> But a warning: almost all compilers got this wrong when we tested them while
> we were working on the Amendment.
[...]

Thanks for clarification. I wrote a simple test that opens an In_File
and then Resets it as Out_File and writing works as expected - data is
overwritten over the bytes that I wish to change and there is no
truncation (the compiler is GNAT GPL 2007).

(I have read A.8.2 File Management and only skimmed over description
of Ada.Streams.Stream_IO, so this has been mostly an RTFM issue :) ).
--
Marcin Simonides




^ permalink raw reply	[relevance 2%]

* Re: Mixing reading and writing to a text file
  2007-08-02  7:43  1% Mixing reading and writing to a text file msimonides
@ 2007-08-03  1:26  2% ` Randy Brukardt
  2007-08-06  7:35  2%   ` msimonides
  0 siblings, 1 reply; 200+ results
From: Randy Brukardt @ 2007-08-03  1:26 UTC (permalink / raw)


<msimonides@power.com.pl> wrote in message
news:1186040606.842876.191850@57g2000hsv.googlegroups.com...
> I'm facing a situation, where I need to access a text file for both
> input and output.

The only way to read and write the same file is using Ada.Streams.Stream_IO.
Use Reset or Set_Mode to change from Reading to Writing and vice versa.

> This file is used for storing a sequence of different records (of
> various lengths - it's not possible to define the upper bound)
> defining operations that need to be performed. Some errors could occur
> and the processing might be aborted. In this case it is crucial to
> store state of the processing (in the simplest case only the number of
> the last record processed) must be saved, so that it may be resumed
> later.
>
> The task seems simple as I have complete control over the file format.
> I'd rather use human-readable format but a binary one is also
> acceptable.
>
> The problem I have is with writing the state information back to file.
> Ada.Text_IO and Ada.Streams.Stream_IO only allow opening file for
> input or for output. In the latter case the file is being truncated
> (as far as I understand the ARM).

The ARM was screwed up in Ada 95 vis-a-vis Ada.Streams.Stream_IO. This was
fixed in the Amendment (and the fix is supposed to apply to Ada 95 compilers
as well). Specifically, stream files are *not* truncated when they are
opened for output (otherwise it would be virtually impossible to use the
positioning functions to write a stream file).

But a warning: almost all compilers got this wrong when we tested them while
we were working on the Amendment. (The main reason that we were willing to
change it was that virtually every compiler tested did something different.)
So it is not impossible that your implementation gets this wrong in some
way. But if it does, that is a compiler bug, not a language issue. Report it
to your implementer.

Also note that you don't need to Open the file to change the mode of a
stream file; Set_Mode should do the job. And even the buggy Ada 95 manual
didn't imply that Set_Mode should truncate, so that ought to work (but
again, not all compilers get this right - unfortunately, there was no ACATS
test for it).

                                   Randy.





^ permalink raw reply	[relevance 2%]

* Mixing reading and writing to a text file
@ 2007-08-02  7:43  1% msimonides
  2007-08-03  1:26  2% ` Randy Brukardt
  0 siblings, 1 reply; 200+ results
From: msimonides @ 2007-08-02  7:43 UTC (permalink / raw)


I'm facing a situation, where I need to access a text file for both
input and output.

This file is used for storing a sequence of different records (of
various lengths - it's not possible to define the upper bound)
defining operations that need to be performed. Some errors could occur
and the processing might be aborted. In this case it is crucial to
store state of the processing (in the simplest case only the number of
the last record processed) must be saved, so that it may be resumed
later.

The task seems simple as I have complete control over the file format.
I'd rather use human-readable format but a binary one is also
acceptable.

The problem I have is with writing the state information back to file.
Ada.Text_IO and Ada.Streams.Stream_IO only allow opening file for
input or for output. In the latter case the file is being truncated
(as far as I understand the ARM).

Currently I'm mixing Text_IO and Direct_IO: Text_IO is used for
reading and writing the file initially and Direct_IO is used to
overwrite the first dozen characters that specify state.
This approach has many deficiencies, of course, like reopening the
file in different mode (which might fail due to permissions).
My first question is: can I freely mix Text_IO and Direct_IO at all?

The main question is: How should I approach this problem?

I've considered using Ada/POSIX binding like Florist but I'm not sure
whether it would be portable to Windows (currently there's no such
requirement in our project, but I don't want to close this path).
--
Marcin Simonides




^ permalink raw reply	[relevance 1%]

* Re: STORAGE_ERROR : EXCEPTION_STACK_OVERFLOW
  2007-04-02  6:13  1% STORAGE_ERROR : EXCEPTION_STACK_OVERFLOW andrew.carroll
    2007-04-02 22:05  1% ` andrew.carroll
@ 2007-04-12 13:48  2% ` andrew.carroll
  2 siblings, 0 replies; 200+ results
From: andrew.carroll @ 2007-04-12 13:48 UTC (permalink / raw)


S.I.T.R.E.P

I changed the GPS compiler to Ada95 and fixed any compiler errors.
Once I did that (and without using dispatching or abstract types) I
was able to get the program _working_, again.  I made some other
changes to the overall design.  The schema type now has it's own file
for 'input and 'output so I don't have to read past it in the file
that contains the tuples.  I implemented accessor methods (set and
get) for the attributes of the attribute types and extentions.  So I
have getValue, setValue...

After all that was working I changed the attribute type to be abstract
and all it's methods to be abstract and implemented the to_disc
procedure again (dispatching for writing to disk).  That part worked.

After that I tried to implement the from_disc function (dispatching
from the disk).  Problem with this one is that when I used it, the
context of the call is for an attribute type and of course attribute
is abstract and therefore cannot be instantiated.  Here is a small
example:

attrib : attribute_ptr;
...
attrib.all := from_disc(fin, obj_of_desired_attribute_class.all)

but in order to do this, attrib has to be "not null" like the
following

attrib: attribute_ptr;
...
attrib := new attribute;
attrib.all := from_disc(fin, obj_of_desired_attribute_class.all)

and of course the type attribute is abstract so it cannot be
instantiated.


So I removed the abstract and implemented the methods for the
attribute type.  Now I can do:

attrib: attribute_ptr;
...
attrib := new attribute;
attrib.all := from_disc(fin, obj_of_desired_attribute_class.all);

but, it only ever dispatches to the from_disc of attribute even though
I've supplied an object of booleanattribute or stringattribute or
dateattribute or integerattribute as the actual parameter.  So now I
have some questions:

1.  If I have the following function defined for attribute type, and
also defined for types extending from attribute type, do they all need
to have attribute'class as the return value so that it dispatches
based on the actual parameter ONLY?

function from_disc(fin :ada.streams.stream_io.file_type; item:
attribute) return attribute;
function from_disc(fin :ada.streams.stream_io.file_type; item:
booleanattribute) return booleanattribute;
function from_disc(fin :ada.streams.stream_io.file_type; item:
integerattribute) return integerattribute;
function from_disc(fin :ada.streams.stream_io.file_type; item:
stringattribute) return stringattribute;
function from_disc(fin :ada.streams.stream_io.file_type; item:
dateattribute) return dateattribute;



The reason the program crashes NOW is because when from_disc is called
it only ever 'inputs an attribute type.  An attribute type is smaller
in size than the other attribute extentions.  So if the file actually
contains a booleanattribute then 'input will not read the full
booleanattribute; just the attribute.  This means that the fin file
pointer is not on end_of_file.  So a loop with the following sentinel;
not end_of_file(fin), will not break (exit) when it should because fin
is not at end_of_file and it will try to read another attribute.  Of
course for my test cases there is only one attribute in the file but
because we are not at end_of_file the program loops and tries to read
another attribute.

If from_disc were dispatching, then the correct extention of attribute
type would be 'input-ed and the fin file pointer would be at end of
file, the loop would exit properly and things would be okay.

Am I making any sense?

Andrew






^ permalink raw reply	[relevance 2%]

* Re: STORAGE_ERROR : EXCEPTION_STACK_OVERFLOW
  2007-04-02  6:13  1% STORAGE_ERROR : EXCEPTION_STACK_OVERFLOW andrew.carroll
  @ 2007-04-02 22:05  1% ` andrew.carroll
  2007-04-12 13:48  2% ` andrew.carroll
  2 siblings, 0 replies; 200+ results
From: andrew.carroll @ 2007-04-02 22:05 UTC (permalink / raw)


I've made some further changes to the program.  I made the following
adjustments to the attribute_types.

type attribute is abstract tagged null record;

and I added the following functions/procedures

function getName (item: attribute) return string is abstract;
procedure setName(item: in out attribute; value: string) is abstract;
function getDomain(item: attribute) return string is abstract;
procedure setDomain(item: in out attribute; value: string) is
abstract;
function getByteEnd(item: attribute) return integer is abstract;
function isprimarykey(item: attribute) return boolean is abstract;
procedure makeprimarykey(item: in out attribute) is abstract;



This way there is not mistaking that it is dispatched.  The reason I
did this is because I tried debugging it to find out what the domain
value of an attribute was in the debug code inside the loadtable
procedure.  I would try to print the .domain field of
schemainfo.attributes(x) and it would kill the debugger.

Since I made the changes the error message is now "raised
PROGRAM_ERROR : EXCEPTION_ACCESS_VIOLATION".  Which if I'm not
mistaken means dangling pointer and that matches to errors I now get
in gdb.


Here is the new attribute_types.adb/ads files





with util, Ada.Calendar, ada.streams.stream_io;

use util, Ada.Calendar, ada.streams.stream_io;

package attribute_types is

    -----------------------------------
    --    Forwarding Declarations    --
    -----------------------------------
    type attribute is abstract tagged;
    type booleanattribute is tagged;
    type integerattribute is tagged;
    type stringattribute is tagged;
    type dateattribute is tagged;

    --------------------------------------
    --    Attribute Type Declarations    --
    --------------------------------------
    type attribute is abstract tagged null record;
--          name         : String (1 .. max_attributename_length) :=
--             (1 .. max_attributename_length => ' ');
--          domain       : String (1 .. max_typename_length) := (1 ..
max_typename_length => ' ');
--          isprimarykey : Boolean                                :=
False;
--          byte_start   : Integer                                :=
0;
--          byte_end     : Integer                                :=
0;
--    end record;

    --------------------------------------
    --    Basic Pointer Declarations    --
    --------------------------------------
    type attribute_ptr is access attribute'class;
--    type attribute_array is array (Integer range <>) of access
attribute'class;
    type attribute_array is array (Integer range <>) of attribute_ptr;
    type attribute_array_ptr is access all attribute_array;

    procedure to_disc (fout: file_type; item: in out attribute) is
abstract;
    function from_disc(fout: file_type; item: attribute) return
attribute'class is abstract;
    function getName (item: attribute) return string is abstract;
    procedure setName(item: in out attribute; value: string) is
abstract;
    function getDomain(item: attribute) return string is abstract;
    procedure setDomain(item: in out attribute; value: string) is
abstract;
    function getByteEnd(item: attribute) return integer is abstract;
    function isprimarykey(item: attribute) return boolean is
abstract;
    procedure makeprimarykey(item: in out attribute) is abstract;

    -----------------------------------
    --    Extended Attribute Types   --
    -----------------------------------
    type booleanattribute is new attribute with record
        name         : String (1 .. max_attributename_length) :=
           (1 .. max_attributename_length => ' ');
        domain       : String (1 .. max_typename_length) := (1 ..
max_typename_length => ' ');
        isprimarykey : Boolean                                :=
False;
        byte_start   : Integer                                := 0;
        byte_end     : Integer                                := 0;
        value : Boolean := False;
    end record;
    type booleanattribute_ptr is access all booleanattribute'class;
    procedure to_disc (fout: file_type; item: in out
booleanattribute);
    function from_disc(fin: file_type; item: booleanattribute) return
attribute'class;
    function getName (item: booleanattribute) return string;
    procedure setName(item: in out booleanattribute; value:
string);
    function getDomain(item: booleanattribute) return string;
    procedure setDomain(item: in out booleanattribute; value:
string);
    function getByteEnd(item: booleanattribute) return integer;
    function isprimarykey(item: booleanattribute) return boolean;
    procedure makeprimarykey(item: in out booleanattribute);

    type integerattribute is new attribute with record
        name         : String (1 .. max_attributename_length) :=
           (1 .. max_attributename_length => ' ');
        domain       : String (1 .. max_typename_length) := (1 ..
max_typename_length => ' ');
        isprimarykey : Boolean                                :=
False;
        byte_start   : Integer                                := 0;
        byte_end     : Integer                                := 0;
        value : Integer := 0;
    end record;
    type integerattribute_ptr is access all integerattribute'class;
    procedure to_disc (fout: file_type; item: in out
integerattribute);
    function from_disc(fin: file_type; item: integerattribute) return
attribute'class;
    function getName (item: integerattribute) return string;
    procedure setName(item: in out integerattribute; value:
string);
    function getDomain(item: integerattribute) return string;
    procedure setDomain(item: in out integerattribute; value:
string);
    function getByteEnd(item: integerattribute) return
integer;
    function isprimarykey(item: integerattribute) return boolean;
    procedure makeprimarykey(item: in out integerattribute);

    type stringattribute is new attribute with record
        name         : String (1 .. max_attributename_length) :=
           (1 .. max_attributename_length => ' ');
        domain       : String (1 .. max_typename_length) := (1 ..
max_typename_length => ' ');
        isprimarykey : Boolean                                :=
False;
        byte_start   : Integer                                := 0;
        byte_end     : Integer                                := 0;
        value : String (1 .. max_stringlength) := (1 ..
max_stringlength => ' ');
    end record;
    type stringattribute_ptr is access all stringattribute'class;
    procedure to_disc (fout: file_type; item: in out stringattribute);
    function from_disc(fin: file_type; item: stringattribute) return
attribute'class;
    function getName (item: stringattribute) return string;
    procedure setName(item: in out stringattribute; value:
string);
    function getDomain(item: stringattribute) return string;
    procedure setDomain(item: in out stringattribute; value:
string);
    function getByteEnd(item: stringattribute) return
integer;
    function isprimarykey(item: stringattribute) return boolean;
    procedure makeprimarykey(item: in out stringattribute);

    type dateattribute is new attribute with record
        name         : String (1 .. max_attributename_length) :=
           (1 .. max_attributename_length => ' ');
        domain       : String (1 .. max_typename_length) := (1 ..
max_typename_length => ' ');
        isprimarykey : Boolean                                :=
False;
        byte_start   : Integer                                := 0;
        byte_end     : Integer                                := 0;
        year  : Year_Number  := 1901;
        month : Month_Number := 1;
        day   : Day_Number   := 1;
        value : Time         := Time_Of (1901, 1, 1);
    end record;
    type dateattribute_ptr is access all dateattribute'class;
    procedure to_disc (fout: file_type; item: in out dateattribute);
    function from_disc(fin: file_type; item: dateattribute) return
attribute'class;
    function getName (item: dateattribute) return string;
    procedure setName(item: in out dateattribute; value:
string);
    function getDomain(item: dateattribute) return string;
    procedure setDomain(item: in out dateattribute; value:
string);
    function getByteEnd(item: dateattribute) return integer;
    function isprimarykey(item: dateattribute) return boolean;
    procedure makeprimarykey(item: in out dateattribute);

end attribute_types;


with ada.text_io, util, ada.calendar;
use util, ada.calendar;

package body attribute_types is

    -------------------------------
    --  BOOLEAN ATTRIBUTE STUFF  --
    -------------------------------
    procedure to_disc (fout: file_type; item: in out booleanattribute)
is
    begin
        item.byte_start := Integer'val (Index (fout));
        item.byte_end := Integer'val (Index (fout)) +
(booleanattribute'size / 8) - 7;
--        booleanattribute'class'output(Stream(fout), item);
        booleanattribute'output(Stream(fout), item);
    end to_disc;

    function from_disc(fin: file_type; item: booleanattribute) return
attribute'class is
        temp : access attribute'class;
    begin
      temp := new booleanattribute;
--      temp.all := booleanattribute'class'input (Stream (fin));
      temp.all := booleanattribute'input (Stream (fin));
      return temp.all;
    end from_disc;

    function getName (item: booleanattribute) return string is
    begin
    	return item.name;
    end getName;

    procedure setName(item: in out booleanattribute; value: string) is
    begin
        item.name := value(value'first - 1 +
item.name'first..item.name'last);
    end setName;

    function getDomain(item: booleanattribute) return string is
    begin
    	return item.domain;
    end getDomain;

    procedure setDomain(item: in out booleanattribute; value: string)
is
    begin
        item.domain := value(value'first - 1 +
item.domain'first..item.domain'last);
    end setdomain;

    function getByteEnd(item: booleanattribute) return integer is
    begin
        return item.byte_end;
    end getByteEnd;

    function isprimarykey(item: booleanattribute) return boolean is
    begin
        return item.isprimarykey;
    end isprimarykey;

    procedure makeprimarykey(item: in out booleanattribute) is
    begin
        item.isprimarykey := true;
    end makeprimarykey;

    -------------------------------
    --  INTEGER ATTRIBUTE STUFF  --
    -------------------------------
    procedure to_disc (fout: file_type; item: in out integerattribute)
is
    begin
        item.byte_start := Integer'val (Index (fout));
        item.byte_end := Integer'val (Index (fout)) +
(integerattribute'size / 8) - 7;
--        integerattribute'class'output(Stream(fout), item);
        integerattribute'output(Stream(fout), item);
    end to_disc;

    function from_disc(fin: file_type; item: integerattribute) return
attribute'class is
    	temp : access attribute'class;
    begin
  	temp := new integerattribute;
--	temp.all := integerattribute'class'input (Stream (fin));
	temp.all := integerattribute'input (Stream (fin));
	return temp.all;
    end from_disc;

    function getName (item: integerattribute) return string is
    begin
        return item.name;
    end getName;

    procedure setName(item: in out integerattribute; value: string) is
    begin
        item.name := value(value'first - 1 +
item.name'first..item.name'last);
    end setName;

    function getDomain(item: integerattribute) return string is
    begin
    	return item.domain;
    end getDomain;

    procedure setDomain(item: in out integerattribute; value: string)
is
    begin
        item.domain := value(value'first - 1 +
item.domain'first..item.domain'last);
    end setdomain;

    function getByteEnd(item: integerattribute) return integer is
    begin
        return item.byte_end;
    end getByteEnd;

    function isprimarykey(item: integerattribute) return boolean is
    begin
        return item.isprimarykey;
    end isprimarykey;

    procedure makeprimarykey(item: in out integerattribute) is
    begin
        item.isprimarykey := true;
    end makeprimarykey;


    ------------------------------
    --  STRING ATTRIBUTE STUFF  --
    ------------------------------
    procedure to_disc (fout: file_type; item: in out stringattribute)
is
    begin
        item.byte_start := Integer'val (Index (fout));
        item.byte_end := Integer'val (Index (fout)) +
(stringattribute'size / 8) - 7;
--        stringattribute'class'output(Stream(fout), item);
        stringattribute'output(Stream(fout), item);
    end to_disc;

    function from_disc(fin: file_type; item: stringattribute) return
attribute'class is
    	temp: access attribute'class;
    begin
  	temp := new stringattribute;
--	temp.all := stringattribute'class'input (Stream (fin));
	temp.all := stringattribute'input (Stream (fin));
	return temp.all;
    end from_disc;

    function getName (item: stringattribute) return string is
    begin
        return item.name;
    end getName;

    procedure setName(item: in out stringattribute; value: string) is
    begin
        item.name := value(value'first - 1 +
item.name'first..item.name'last);
    end setName;

    function getDomain(item: stringattribute) return string is
    begin
    	return item.domain;
    end getDomain;

    procedure setDomain(item: in out stringattribute; value: string)
is
    begin
        item.domain := value(value'first - 1 +
item.domain'first..item.domain'last);
    end setdomain;

    function getByteEnd(item: stringattribute) return integer is
    begin
        return item.byte_end;
    end getByteEnd;

    function isprimarykey(item: stringattribute) return boolean is
    begin
        return item.isprimarykey;
    end isprimarykey;

    procedure makeprimarykey(item: in out stringattribute) is
    begin
        item.isprimarykey := true;
    end makeprimarykey;


    ----------------------------
    --  DATE ATTRIBUTE STUFF  --
    ----------------------------
    procedure to_disc (fout: file_type; item: in out dateattribute) is
    begin
        item.byte_start := Integer'val (Index (fout));
        item.byte_end := Integer'val (Index (fout)) +
(dateattribute'size / 8) - 11;
--        dateattribute'class'output(Stream(fout), item);
        dateattribute'output(Stream(fout), item);
    end to_disc;

    function from_disc(fin: file_type; item: dateattribute) return
attribute'class is
    	temp: access attribute'class;
    begin
    	temp := new dateattribute;
--	temp.all := dateattribute'class'input (Stream (fin));
	temp.all := dateattribute'input (Stream (fin));
	return temp.all;
    end from_disc;

    function getName (item: dateattribute) return string is
    begin
        return item.name;
    end getName;

    procedure setName(item: in out dateattribute; value: string) is
    begin
        item.name := value(value'first - 1 +
item.name'first..item.name'last);
    end setName;

    function getDomain(item: dateattribute) return string is
    begin
    	return item.domain;
    end getDomain;

    procedure setDomain(item: in out dateattribute; value: string) is
    begin
        item.domain := value(value'first - 1 +
item.domain'first..item.domain'last);
    end setdomain;

    function getByteEnd(item: dateattribute) return integer is
    begin
        return item.byte_end;
    end getByteEnd;

    function isprimarykey(item: dateattribute) return boolean is
    begin
        return item.isprimarykey;
    end isprimarykey;

    procedure makeprimarykey(item: in out dateattribute) is
    begin
        item.isprimarykey := true;
    end makeprimarykey;

begin
    null;
end attribute_types;









^ permalink raw reply	[relevance 1%]

* Re: STORAGE_ERROR : EXCEPTION_STACK_OVERFLOW
  @ 2007-04-02 14:11  1%   ` andrew.carroll
  0 siblings, 0 replies; 200+ results
From: andrew.carroll @ 2007-04-02 14:11 UTC (permalink / raw)


All the files are below.  The last file in the list, called
tables.txt, is the input file.  I've supplied the input file I am
using when I get the errors.





with Ada.Text_IO, Ada.Directories, GNAT.Calendar.Time_IO,
Ada.Characters.Latin_1, Ada.IO_Exceptions,
 Ada.Strings.Maps.Constants, Ada.Strings.Fixed,
Ada.Characters.Handling, Ada.Calendar,
 schema_types, attribute_types, parser, util, index_types;

use parser, GNAT.Calendar.Time_IO, Ada.Characters.Latin_1,
Ada.Strings.Maps.Constants, Ada.Strings.Fixed,
Ada.Characters.Handling, Ada.Calendar, schema_types, attribute_types,
util;

procedure dbprog is

    -- the input file contains the table specifications --
    input : Ada.Text_IO.File_Type;

    ------------------------------------
    --    Variables for Processing    --
    ------------------------------------
    char      : Character;
    line      : string_ptr;
    tablename : string_ptr;
    datacols  : string_array_ptr;
    pkcols    : string_array_ptr;
    schemas   : schema_array_ptr;
    sindex    : Integer := 1;
    tupls     : tuple_ptr;

    procedure showoptionsmenu is
    begin
        cls;
        pl ("---------------------------------------------------",
True);
        pl ("Type one of the following at the prompt:", True);
        pl (" ", True);
        pl ("~  QUIT ", True);
        pl ("1  INSERT DATA", True);
        pl ("2  UPDATE DATA", True);
        pl ("3  DELETE DATA", True);
        pl ("4  SHOW RECORDS", True);
        pl ("For help type 'help'", True);
        pl ("---------------------------------------------------",
True);
        pl (">>", False);

        while Ada.Text_IO.End_Of_Line loop
            Ada.Text_IO.Skip_Line;
        end loop;

        line := new String'(Ada.Text_IO.Get_Line);

    end showoptionsmenu;

    function markschema return Integer is
        idx : Integer := 0;
    begin
        --find the schema in schemas.
        if schemas'length <= 0 then
            return idx;
        end if;

        loop
            idx := idx + 1;
            exit when idx > schemas'length
                     or else Index (To_Upper (schemas
(idx).tablename), tablename.all) > 0;
        end loop;

        return idx;

    end markschema;

    procedure getcolumnnamesandvalues is
        year  : Year_Number;
        month : Month_Number;
        day   : Day_Number;
        line  : string_ptr := new String'("");
        valid : Boolean    := False;
    begin
        --markschema sets sindex to the appropriate index in schemas
        --for the table with tablename.
        sindex := markschema;

        --tables are already loaded and ready to go.
        datacols := new string_array (1 .. schemas
(sindex).attributes'length);

        for x in  1 .. schemas (sindex).attributes'length loop
            if Trim (schemas (sindex).attributes (x).domain,
Ada.Strings.Both) = "DATE" then

                while not valid loop
                    pl
                       ("Enter a YEAR (1901 - 2099) for " &
                        Trim (schemas (sindex).attributes (x).name,
Ada.Strings.Both) &
                        "  >>",
                        False,
                        False);

                    while Ada.Text_IO.End_Of_Line loop
                        Ada.Text_IO.Skip_Line;
                    end loop;

                    line := new String'(Ada.Text_IO.Get_Line);

                    if Index (line.all, Decimal_Digit_Set,
Ada.Strings.Outside) > 0 then
                        pl ("!! INVALID !!", True, False);
                    elsif Index (line.all, Decimal_Digit_Set,
Ada.Strings.Outside) <= 0
                       and then Integer'value (line.all) not  in
Ada.Calendar.Year_Number'range
                    then
                        pl ("!! INVALID !!", True, False);
                    else
                        valid := True;
                    end if;
                end loop;

                year  := Year_Number'value (line.all);
                valid := False;

                while not valid loop
                    pl
                       ("Enter a MONTH NUMBER for " &
                        Trim (schemas (sindex).attributes (x).name,
Ada.Strings.Both) &
                        "  >>",
                        False,
                        False);

                    while Ada.Text_IO.End_Of_Line loop
                        Ada.Text_IO.Skip_Line;
                    end loop;

                    line := new String'(Ada.Text_IO.Get_Line);

                    if Index (line.all, Decimal_Digit_Set,
Ada.Strings.Outside) > 0 then
                        pl ("!! INVALID !!", True, False);
                    elsif Index (line.all, Decimal_Digit_Set,
Ada.Strings.Outside) <= 0
                       and then Integer'value (line.all) not  in
Ada.Calendar.Month_Number'range
                    then
                        pl ("!! INVALID !!", True, False);
                    else
                        valid := True;
                    end if;
                end loop;

                month := Month_Number'value (line.all);
                valid := False;

                while not valid loop
                    pl
                       ("Enter a DAY NUMBER for " &
                        Trim (schemas (sindex).attributes (x).name,
Ada.Strings.Both) &
                        "  >>",
                        False,
                        False);

                    while Ada.Text_IO.End_Of_Line loop
                        Ada.Text_IO.Skip_Line;
                    end loop;

                    line := new String'(Ada.Text_IO.Get_Line);

                    if Index (line.all, Decimal_Digit_Set,
Ada.Strings.Outside) > 0 then
                        pl ("!! INVALID !!", True, False);
                    elsif Index (line.all, Decimal_Digit_Set,
Ada.Strings.Outside) <= 0
                       and then Integer'value (line.all) not  in
Ada.Calendar.Day_Number'range
                    then
                        pl ("!! INVALID !!", True, False);
                    else
                        valid := True;
                    end if;
                end loop;

                day              := Day_Number'value (line.all);
                datacols.all (x) := new String'(Image (Time_Of (year,
month, day), ISO_Date));
                valid            := False;
            else
                while not valid loop
                    pl
                       ("Enter a value for " &
                        Trim (schemas (sindex).attributes (x).name,
Ada.Strings.Both) &
                        "(" &
                        Trim (schemas (sindex).attributes (x).domain,
Ada.Strings.Both) &
                        ")  >>",
                        False,
                        False);

                    while Ada.Text_IO.End_Of_Line loop
                        Ada.Text_IO.Skip_Line;
                    end loop;

                    line := new String'(Ada.Text_IO.Get_Line);

                    if Trim (schemas (sindex).attributes (x).domain,
Ada.Strings.Both) =
                       "BOOLEAN"
                    then
                        if To_Upper (line.all) = "TRUE" then
                            line  := new String'("True");
                            valid := True;
                        elsif To_Upper (line.all) = "FALSE" then
                            line  := new String'("False");
                            valid := True;
                        elsif line.all = "1" then
                            line  := new String'("True");
                            valid := True;
                        elsif line.all = "0" then
                            line  := new String'("False");
                            valid := True;
                        else
                            pl ("!! INVALID !!", True, False);
                        end if;
                    elsif Trim (schemas (sindex).attributes
(x).domain, Ada.Strings.Both) =
                          "INTEGER"
                    then
                        if Index (line.all, Decimal_Digit_Set,
Ada.Strings.Outside) <= 0 then
                            valid := True;
                        else
                            pl ("!! INVALID !!", True, False);
                        end if;
                    else --"STRING"
                        valid := True;
                    end if;

                end loop;

                valid            := False;
                datacols.all (x) := new String'(line.all);
            end if;

        end loop;

    end getcolumnnamesandvalues;

    procedure getprimarykeynamesandvalues is
        year  : Year_Number;
        month : Month_Number;
        day   : Day_Number;
        line  : string_ptr := new String'("");
        valid : Boolean    := False;
    begin
        --markschema sets sindex to the appropriate index in schemas
        --for the table with tablename.
        sindex := markschema;

        pl ("Provide the primary key values to identify the record to
delete.", False, True);
        pl ("Press Enter to continue...", True, True);
        Ada.Text_IO.Get_Immediate (char);

        --tables are already loaded and ready to go.
        pkcols := new string_array (1 .. schemas
(sindex).primary_key_count);

        for x in  1 .. schemas (sindex).attributes'length loop
            if schemas (sindex).attributes (x).isprimarykey then
                if Trim (schemas (sindex).attributes (x).domain,
Ada.Strings.Both) = "DATE" then

                    while not valid loop
                        pl
                           ("Enter a YEAR (1901 - 2099) for " &
                            Trim (schemas (sindex).attributes
(x).name, Ada.Strings.Both) &
                            "  >>",
                            False,
                            False);

                        while Ada.Text_IO.End_Of_Line loop
                            Ada.Text_IO.Skip_Line;
                        end loop;

                        line := new String'(Ada.Text_IO.Get_Line);

                        if Index (line.all, Decimal_Digit_Set,
Ada.Strings.Outside) > 0 then
                            pl ("!! INVALID !!", True, False);
                        elsif Index (line.all, Decimal_Digit_Set,
Ada.Strings.Outside) <= 0
                           and then Integer'value (line.all) not  in
Ada.Calendar.Year_Number'range
                        then
                            pl ("!! INVALID !!", True, False);
                        else
                            valid := True;
                        end if;
                    end loop;

                    year  := Year_Number'value (line.all);
                    valid := False;

                    while not valid loop
                        pl
                           ("Enter a MONTH NUMBER for " &
                            Trim (schemas (sindex).attributes
(x).name, Ada.Strings.Both) &
                            "  >>",
                            False,
                            False);

                        while Ada.Text_IO.End_Of_Line loop
                            Ada.Text_IO.Skip_Line;
                        end loop;

                        line := new String'(Ada.Text_IO.Get_Line);

                        if Index (line.all, Decimal_Digit_Set,
Ada.Strings.Outside) > 0 then
                            pl ("!! INVALID !!", True, False);
                        elsif Index (line.all, Decimal_Digit_Set,
Ada.Strings.Outside) <= 0
                           and then Integer'value (line.all) not  in
Ada.Calendar.Month_Number'
                             range
                        then
                            pl ("!! INVALID !!", True, False);
                        else
                            valid := True;
                        end if;
                    end loop;

                    month := Month_Number'value (line.all);
                    valid := False;

                    while not valid loop
                        pl
                           ("Enter a DAY NUMBER for " &
                            Trim (schemas (sindex).attributes
(x).name, Ada.Strings.Both) &
                            "  >>",
                            False,
                            False);

                        while Ada.Text_IO.End_Of_Line loop
                            Ada.Text_IO.Skip_Line;
                        end loop;

                        line := new String'(Ada.Text_IO.Get_Line);

                        if Index (line.all, Decimal_Digit_Set,
Ada.Strings.Outside) > 0 then
                            pl ("!! INVALID !!", True, False);
                        elsif Index (line.all, Decimal_Digit_Set,
Ada.Strings.Outside) <= 0
                           and then Integer'value (line.all) not  in
Ada.Calendar.Day_Number'range
                        then
                            pl ("!! INVALID !!", True, False);
                        else
                            valid := True;
                        end if;
                    end loop;

                    day            := Day_Number'value (line.all);
                    pkcols.all (x) := new String'(Image (Time_Of
(year, month, day), ISO_Date));
                    valid          := False;
                else
                    while not valid loop
                        pl
                           ("Enter a value for " &
                            Trim (schemas (sindex).attributes
(x).name, Ada.Strings.Both) &
                            "(" &
                            Trim (schemas (sindex).attributes
(x).domain, Ada.Strings.Both) &
                            ")  >>",
                            False,
                            False);

                        while Ada.Text_IO.End_Of_Line loop
                            Ada.Text_IO.Skip_Line;
                        end loop;

                        line := new String'(Ada.Text_IO.Get_Line);

                        if Trim (schemas (sindex).attributes
(x).domain, Ada.Strings.Both) =
                           "BOOLEAN"
                        then
                            if To_Upper (line.all) = "TRUE" then
                                line  := new String'("True");
                                valid := True;
                            elsif To_Upper (line.all) = "FALSE" then
                                line  := new String'("False");
                                valid := True;
                            elsif line.all = "1" then
                                line  := new String'("True");
                                valid := True;
                            elsif line.all = "0" then
                                line  := new String'("False");
                                valid := True;
                            else
                                pl ("!! INVALID !!", True, False);
                            end if;
                        elsif Trim (schemas (sindex).attributes
(x).domain, Ada.Strings.Both) =
                              "INTEGER"
                        then
                            if Index (line.all, Decimal_Digit_Set,
Ada.Strings.Outside) <=
                               0
                            then
                                valid := True;
                            else
                                pl ("!! INVALID !!", True, False);
                            end if;
                        else --"STRING"
                            valid := True;
                        end if;

                    end loop;

                    valid          := False;
                    pkcols.all (x) := new String'(line.all);
                end if;
            end if;

        end loop;
    end getprimarykeynamesandvalues;

    procedure gettablename is
        count : Integer := 1;
    begin
        pl ("Enter the table name in CAPITAL letters >>", False);
        tablename     := new String'(Ada.Text_IO.Get_Line);
        tablename.all := To_Upper (tablename.all);

        while not Ada.Directories.Exists (tablename.all) and count < 5
loop
            pl ("Enter the table name in CAPITAL letters >>", False);
            tablename     := new String'(Ada.Text_IO.Get_Line);
            tablename.all := To_Upper (tablename.all);
            count         := count + 1;
        end loop;

        if count >= 5 then
            raise Constraint_Error;
        end if;

    end gettablename;

    procedure getchosenoptiondata is
    begin
        gettablename;

        --we don't do "4" here because it is just a select and we
don't
        --need values for it and we already have the attribute names
in
        --the schemas(sindex) object for which to SELECT or SHOW the
        --data.
        if line.all = "1" then
            getcolumnnamesandvalues;
        elsif line.all = "2" then
            getprimarykeynamesandvalues;
            pl (" ", True, True);
            pl ("Please enter new values for each item.  You can enter
the same ", True, True);
            pl ("data if you don't want it modified.", True, True);
            pl (" ", True, True);
            getcolumnnamesandvalues;
        elsif line.all = "3" then
            getprimarykeynamesandvalues;

        end if;

    end getchosenoptiondata;

    procedure parsechosenoption is
        pkattribs  : attribute_array_ptr;
        newvalues  : attribute_array_ptr;
        linelength : Integer;
        outline    : string_ptr;
    begin
        if line.all = "1" then

            -------------------
            --  INSERT DATA  --
            -------------------
            newvalues := new attribute_array (1 .. schemas
(sindex).attributes'length);

            --fill in the values on the objects and pass that to
insert.
            for x in  1 .. newvalues'length loop
                if Trim (schemas (sindex).attributes (x).domain,
Ada.Strings.Both) =
                   "BOOLEAN"
                then
                    newvalues (x) :=
                     new booleanattribute'
                       (name         => schemas (sindex).attributes
(x).name,
                        domain       => schemas (sindex).attributes
(x).domain,
                        isprimarykey => schemas (sindex).attributes
(x).isprimarykey,
                        byte_start   => 0,
                        byte_end     => 0,
                        value        => Boolean'value (datacols
(x).all));
                elsif Trim (schemas (sindex).attributes (x).domain,
Ada.Strings.Both) =
                      "STRING"
                then
                    newvalues (x) :=
                     new stringattribute'
                       (name         => schemas (sindex).attributes
(x).name,
                        domain       => schemas (sindex).attributes
(x).domain,
                        isprimarykey => schemas (sindex).attributes
(x).isprimarykey,
                        byte_start   => 0,
                        byte_end     => 0,
                        value        => max_stringlength * ' ');

                    Replace_Slice
                       (stringattribute (newvalues (x).all).value,
                        1,
                        max_stringlength,
                        datacols (x).all);

                elsif Trim (schemas (sindex).attributes (x).domain,
Ada.Strings.Both) =
                      "INTEGER"
                then
                    newvalues (x) :=
                     new integerattribute'
                       (name         => schemas (sindex).attributes
(x).name,
                        domain       => schemas (sindex).attributes
(x).domain,
                        isprimarykey => schemas (sindex).attributes
(x).isprimarykey,
                        byte_start   => 0,
                        byte_end     => 0,
                        value        => Integer'value (datacols
(x).all));

                else -- "DATE"
                    newvalues (x) :=
                     new dateattribute'
                       (name         => schemas (sindex).attributes
(x).name,
                        domain       => schemas (sindex).attributes
(x).domain,
                        isprimarykey => schemas (sindex).attributes
(x).isprimarykey,
                        byte_start   => 0,
                        byte_end     => 0,
                        value        => Value (datacols (x).all),
                        year         => Year (Value (datacols
(x).all)),
                        month        => Month (Value (datacols
(x).all)),
                        day          => Day (Value (datacols
(x).all)));
                end if;
            end loop;

            insertrec (schemas (sindex).all, newvalues.all);

        elsif line.all = "2" then

            -------------------
            --  UPDATE DATA  --
            -------------------
            pkattribs := new attribute_array (1 .. pkcols'length);

            --fill in the values on the objects and pass that to
insert.
            for x in  1 .. pkcols'length loop
                if Trim (schemas (sindex).attributes (x).domain,
Ada.Strings.Both) =
                   "BOOLEAN"
                then
                    pkattribs (x) :=
                     new booleanattribute'
                       (name         => schemas (sindex).attributes
(x).name,
                        domain       => schemas (sindex).attributes
(x).domain,
                        isprimarykey => schemas (sindex).attributes
(x).isprimarykey,
                        byte_start   => 0,
                        byte_end     => 0,
                        value        => Boolean'value (pkcols
(x).all));
                elsif Trim (schemas (sindex).attributes (x).domain,
Ada.Strings.Both) =
                      "STRING"
                then

                    pkattribs (x) :=
                     new stringattribute'
                       (name         => schemas (sindex).attributes
(x).name,
                        domain       => schemas (sindex).attributes
(x).domain,
                        isprimarykey => schemas (sindex).attributes
(x).isprimarykey,
                        byte_start   => 0,
                        byte_end     => 0,
                        value        => max_stringlength * ' ');

                    Replace_Slice
                       (stringattribute (pkattribs (x).all).value,
                        1,
                        max_stringlength,
                        pkcols (x).all);

                elsif Trim (schemas (sindex).attributes (x).domain,
Ada.Strings.Both) =
                      "INTEGER"
                then
                    pkattribs (x) :=
                     new integerattribute'
                       (name         => schemas (sindex).attributes
(x).name,
                        domain       => schemas (sindex).attributes
(x).domain,
                        isprimarykey => schemas (sindex).attributes
(x).isprimarykey,
                        byte_start   => 0,
                        byte_end     => 0,
                        value        => Integer'value (pkcols
(x).all));

                else -- "DATE"
                    pkattribs (x) :=
                     new dateattribute'
                       (name         => schemas (sindex).attributes
(x).name,
                        domain       => schemas (sindex).attributes
(x).domain,
                        isprimarykey => schemas (sindex).attributes
(x).isprimarykey,
                        byte_start   => 0,
                        byte_end     => 0,
                        value        => Value (pkcols (x).all),
                        year         => Year (Value (pkcols (x).all)),
                        month        => Month (Value (pkcols
(x).all)),
                        day          => Day (Value (pkcols (x).all)));
                end if;
            end loop;

            newvalues := new attribute_array (1 .. schemas
(sindex).attributes'length);

            --fill in the values on the objects and pass that to
insert.
            for x in  1 .. newvalues'length loop
                if Trim (schemas (sindex).attributes (x).domain,
Ada.Strings.Both) =
                   "BOOLEAN"
                then
                    newvalues (x) :=
                     new booleanattribute'
                       (name         => schemas (sindex).attributes
(x).name,
                        domain       => schemas (sindex).attributes
(x).domain,
                        isprimarykey => schemas (sindex).attributes
(x).isprimarykey,
                        byte_start   => 0,
                        byte_end     => 0,
                        value        => Boolean'value (datacols
(x).all));
                elsif Trim (schemas (sindex).attributes (x).domain,
Ada.Strings.Both) =
                      "STRING"
                then
                    newvalues (x) :=
                     new stringattribute'
                       (name         => schemas (sindex).attributes
(x).name,
                        domain       => schemas (sindex).attributes
(x).domain,
                        isprimarykey => schemas (sindex).attributes
(x).isprimarykey,
                        byte_start   => 0,
                        byte_end     => 0,
                        value        => max_stringlength * ' ');

                    Replace_Slice
                       (stringattribute (newvalues (x).all).value,
                        1,
                        max_stringlength,
                        datacols (x).all);

                elsif Trim (schemas (sindex).attributes (x).domain,
Ada.Strings.Both) =
                      "INTEGER"
                then
                    newvalues (x) :=
                     new integerattribute'
                       (name         => schemas (sindex).attributes
(x).name,
                        domain       => schemas (sindex).attributes
(x).domain,
                        isprimarykey => schemas (sindex).attributes
(x).isprimarykey,
                        byte_start   => 0,
                        byte_end     => 0,
                        value        => Integer'value (datacols
(x).all));

                else -- "DATE"
                    newvalues (x) :=
                     new dateattribute'
                       (name         => schemas (sindex).attributes
(x).name,
                        domain       => schemas (sindex).attributes
(x).domain,
                        isprimarykey => schemas (sindex).attributes
(x).isprimarykey,
                        byte_start   => 0,
                        byte_end     => 0,
                        value        => Value (datacols (x).all),
                        year         => Year (Value (datacols
(x).all)),
                        month        => Month (Value (datacols
(x).all)),
                        day          => Day (Value (datacols
(x).all)));
                end if;
            end loop;

            updaterec (schemas (sindex).all, pkattribs.all,
newvalues.all);

        elsif line.all = "3" then

            -------------------
            --  DELETE DATA  --
            -------------------
            Ada.Text_IO.Put_Line (Integer'image (sindex));
            Ada.Text_IO.Put_Line (tablename.all);

            pkattribs := new attribute_array (1 .. pkcols'length);

            --fill in the values on the objects and pass that to
delete.
            for x in  1 .. pkcols'length loop
                if Trim (schemas (sindex).attributes (x).domain,
Ada.Strings.Both) =
                   "BOOLEAN"
                then
                    pkattribs (x) :=
                     new booleanattribute'
                       (name         => schemas (sindex).attributes
(x).name,
                        domain       => schemas (sindex).attributes
(x).domain,
                        isprimarykey => schemas (sindex).attributes
(x).isprimarykey,
                        byte_start   => 0,
                        byte_end     => 0,
                        value        => Boolean'value (pkcols
(x).all));
                elsif Trim (schemas (sindex).attributes (x).domain,
Ada.Strings.Both) =
                      "STRING"
                then

                    pkattribs (x) :=
                     new stringattribute'
                       (name         => schemas (sindex).attributes
(x).name,
                        domain       => schemas (sindex).attributes
(x).domain,
                        isprimarykey => schemas (sindex).attributes
(x).isprimarykey,
                        byte_start   => 0,
                        byte_end     => 0,
                        value        => max_stringlength * ' ');

                    Replace_Slice
                       (stringattribute (pkattribs (x).all).value,
                        1,
                        max_stringlength,
                        pkcols (x).all);

                elsif Trim (schemas (sindex).attributes (x).domain,
Ada.Strings.Both) =
                      "INTEGER"
                then
                    pkattribs (x) :=
                     new integerattribute'
                       (name         => schemas (sindex).attributes
(x).name,
                        domain       => schemas (sindex).attributes
(x).domain,
                        isprimarykey => schemas (sindex).attributes
(x).isprimarykey,
                        byte_start   => 0,
                        byte_end     => 0,
                        value        => Integer'value (pkcols
(x).all));

                else -- "DATE"
                    pkattribs (x) :=
                     new dateattribute'
                       (name         => schemas (sindex).attributes
(x).name,
                        domain       => schemas (sindex).attributes
(x).domain,
                        isprimarykey => schemas (sindex).attributes
(x).isprimarykey,
                        byte_start   => 0,
                        byte_end     => 0,
                        value        => Value (pkcols (x).all),
                        year         => Year (Value (pkcols (x).all)),
                        month        => Month (Value (pkcols
(x).all)),
                        day          => Day (Value (pkcols (x).all)));
                end if;
            end loop;

            deleterec (schemas (sindex).all, pkattribs.all);

        elsif line.all = "4" then

            ----------------------
            --  SELECT RECORDS  --
            ----------------------
            linelength := 60;
            sindex     := markschema;
            outline    := new String'(1 .. linelength => '-');
            pl (outline.all, True, False);
            pl (schemas (sindex).tablename, True, False);
            pl (outline.all, True, False);
            pl ("| ", False, False);
            for x in  1 .. schemas (sindex).attributes'length loop
                pl (Trim (schemas (sindex).attributes (x).name,
Ada.Strings.Both), False, False);

                if x < schemas (sindex).attributes'length then
                    pl (" | ", False, False);
                end if;

            end loop;
            pl (" |", True, False);
            pl (outline.all, True, False);

            tupls := selectrec (schemas (sindex).all);

            if tupls = null then
                pl ("No Data", True, False);
            else
                for y in  1 .. tupls'length loop
                    newvalues := tupls (y);

                    for x in  1 .. newvalues'length loop
                        if Trim (newvalues (x).domain,
Ada.Strings.Both) = "BOOLEAN" then
                            pl
                               (Trim
                                    (Boolean'image (booleanattribute
(newvalues (x).all).value),
                                     Ada.Strings.Both),
                                False,
                                False);
                        elsif Trim (newvalues (x).domain,
Ada.Strings.Both) = "STRING" then
                            pl
                               (Trim
                                    (stringattribute (newvalues
(x).all).value,
                                     Ada.Strings.Both),
                                False,
                                False);
                        elsif Trim (newvalues (x).domain,
Ada.Strings.Both) = "INTEGER" then
                            pl
                               (Trim
                                    (Integer'image (integerattribute
(newvalues (x).all).value),
                                     Ada.Strings.Both),
                                False,
                                False);
                        else -- "DATE"
                            pl
                               (Trim
                                    (Image (dateattribute (newvalues
(x).all).value, ISO_Date),
                                     Ada.Strings.Both),
                                False,
                                False);
                        end if;

                        if x < newvalues'length then
                            pl ("   ", False, False);
                        end if;

                    end loop;
                    pl (" ", True, False);
                end loop;
            end if;

            pl (outline.all, True, False);
            pl ("Press Enter  >>", False, False);
            Ada.Text_IO.Get_Immediate (char);
        end if;

        sindex    := 0;
        tablename := null;
        datacols  := null;
        pkcols    := null;
        tupls     := null;

    end parsechosenoption;

begin

    cls;
    pl ("---------------------------------------------------", True);
    pl ("Put your table definitions in a file named ", True);
    pl ("tables.txt and place the file in the same folder as", True);
    pl ("this program (Parser.exe).  Type C to continue or.", True);
    pl ("~ to quit.", True);
    pl ("---------------------------------------------------", True);
    pl (">>", False);
    Ada.Text_IO.Get (char);
    line := new String'(Ada.Text_IO.Get_Line);

    if char = ETX or char = Tilde then
        raise Ada.IO_Exceptions.End_Error;
    end if;

    setinputfile ("tables.txt");
    schemas := parsetables;
    closeinputfile;
    showoptionsmenu;

    while line.all /= "~" loop

        if line.all = "help" or line.all = "HELP" then
            pl ("---------------------------------------------------",
True);
            pl ("If you want to quit type the tilde '~' character",
True);
            pl ("---------------------------------------------------",
True);
            pl (">>", False);
            line := new String'(Ada.Text_IO.Get_Line);
            cls;
        elsif line.all = "goodbye" or
              line.all = "GOODBYE" or
              line.all = "exit" or
              line.all = "EXIT" or
              line.all = "quit" or
              line.all = "QUIT" or
              line.all = "q" or
              line.all = "Q"
        then
            line := new String'("~");
        else
            ------------------------
            --   output results   --
            ------------------------
            getchosenoptiondata;
            parsechosenoption;
            showoptionsmenu;

        end if;

    end loop;

    cls;
    pl ("---------------------------------------------------", True);
    pl ("Goodbye!", True);
    pl ("---------------------------------------------------", True);

exception
    when Ada.IO_Exceptions.End_Error =>
        if Ada.Text_IO.Is_Open (input) then
            Ada.Text_IO.Close (input);
        end if;
        cls;
        pl ("---------------------------------------------------",
True);
        pl ("An error occured while reading data.  Possibly a
missing", True);
        pl ("semi-colon or other format character.  Or, you pressed ",
True);
        pl ("CTRL + C.  Goodbye!", True);
        pl ("---------------------------------------------------",
True);

    when Ada.Calendar.Time_Error =>
        pl ("A date value was not entered correctly.", True);
        pl ("Unfortunately this will cause the program to exit.",
True);
        pl ("Your data is safe so long as you don't 'create fresh'.",
True);
        pl ("the table when you start the program again.", True);
    when Ada.IO_Exceptions.Data_Error =>
        if Ada.Text_IO.Is_Open (input) then
            Ada.Text_IO.Close (input);
        end if;
    when Constraint_Error =>
        Ada.Text_IO.Put_Line ("You entered the data wrong.");

end dbprog;


with Ada.Text_IO, schema_types, attribute_types;

use schema_types, attribute_types;

package parser is

    file : Ada.Text_IO.File_Type;

    ---------------------------
    --    Utility Methods    --
    ---------------------------
    procedure setinputfile (filename : String);
    procedure closeinputfile;
    function parsetables return schema_array_ptr;
    function parsetable return schema'class;
    function parseattributes return attribute_array_ptr;
    function parseattribute return attribute'class;

end parser;


with Ada.Text_IO, Ada.Directories, Ada.Integer_Text_IO,
Ada.Strings.Fixed, Ada.Characters.Latin_1,
 Ada.IO_Exceptions, schema_types, attribute_types, util;

use Ada.Strings.Fixed, Ada.Characters.Latin_1, schema_types,
attribute_types, util;

package body parser is

    procedure setinputfile (filename : String) is

    begin
        Ada.Text_IO.Open (file, Ada.Text_IO.In_File, filename);
    end setinputfile;

    procedure closeinputfile is
    begin
        if Ada.Text_IO.Is_Open (file) then
            Ada.Text_IO.Close (file);
        end if;
    end closeinputfile;

    -----------------------
    --    parseTables    --
    -----------------------
    function parsetables return schema_array_ptr is
        eof        : Boolean          := False;
        char       : Character;
        schemas    : schema_array_ptr := null;
        swap       : schema_array_ptr := null;
        schemainfo : schema_ptr       := null;
        i          : Integer          := 1;
    begin
        eatWhite (file, eof);

        if not eof then
            Ada.Text_IO.Look_Ahead (file, char, eof);
        else
            raise Ada.IO_Exceptions.End_Error;
        end if;

        --at this point we should be ready to read the table name.
        swap := new schema_array (1 .. max_tables);

        while not eof loop

            schemainfo := new schema'class'(parsetable);

            pl ("Create the table fresh? [y/Y] >>", False, True);
            Ada.Text_IO.Get (char);

	    swap(i) := new schema(schemainfo.attributes'length);

            if char = 'y' or char = 'Y' then
                swap (i)     := schemainfo;
                createtable (swap (i));
            else
                if Ada.Directories.Exists (schemainfo.tablename) then
                    swap (i) := loadtable (schemainfo.tablename);
                else
                    pl ("No table exists on disc with name = " &
schemainfo.tablename, True, True);
                    pl ("You will not be able to query " &
schemainfo.tablename, True, True);
                    pl (" ", True, False);
                end if;
            end if;

	    i := i + 1;
            eatWhite (file, eof);

            if not eof then
                Ada.Text_IO.Look_Ahead (file, char, eof);
            end if;
        end loop;

        i := i - 1;

        if i < 1 then
            schemas := null;
            swap    := null;
        else
            schemas := new schema_array (1 .. i);

            for x in  1 .. i loop
                schemas (x) := swap (x);
            end loop;

            swap := null;

        end if;

        return schemas;

    end parsetables;

    ----------------------
    --    parseTable    --
    ----------------------
    function parsetable return schema'class is
        temp    : schema_ptr := null;
        eof     : Boolean    := False;
        char    : Character;
        tname   : String (1 .. max_tablename_length);
        attribs : attribute_array_ptr;
        i       : Integer    := 1;
    begin

        eatWhite (file, eof);

        --at this point we should be ready to read the table name.
        --the call to eatwhite might be redundant from the instance
that
        --called 'me' but we want to ensure we are in the right
location within
        --the file.
        if not eof then
            Ada.Text_IO.Look_Ahead (file, char, eof);
        else
            raise Ada.IO_Exceptions.End_Error;
        end if;

        while char /= Space and
              char /= HT and
              char /= LF and
              char /= CR and
              char /= Left_Parenthesis and
              not eof
        loop

            Ada.Text_IO.Get (file, char);
            tname (i) := char;
            i         := i + 1;
            Ada.Text_IO.Look_Ahead (file, char, eof);
        end loop;

        for x in  i .. max_tablename_length loop
            tname (x) := ' ';
        end loop;

        --We just read the table name.  We are expecting an opening
'('.
        --If it's not there then there is a problem with the input
file
        --format.
        eatWhite (file, eof);

        if not eof then
            Ada.Text_IO.Look_Ahead (file, char, eof);

            if char = Left_Parenthesis then
                Ada.Text_IO.Get (file, char);
            else
                Ada.Text_IO.Put_Line(
"        Error in input file format:  No attributes found.  Must have
(<attribute list>)");
            end if;
        else
            raise Ada.IO_Exceptions.End_Error;
        end if;

        attribs := parseattributes;

        if attribs /= null then

            temp            := new schema (attribs.all'length);
            temp.attributes := attribs.all;
            temp.tablename  := tname;

            for x in  1 .. temp.attributes'length loop
                if temp.attributes (x).all.isprimarykey then
                    temp.primary_key_count := temp.primary_key_count +
1;
                end if;
            end loop;
        else
            temp := null;
        end if;

        --at this point we should have read the ')' for the whole
table spec.
        --if we peek, we should find a ';'.
        eatWhite (file, eof);

        if not eof then
            Ada.Text_IO.Look_Ahead (file, char, eof);

            if char = Semicolon then
                Ada.Text_IO.Get (file, char);
            else
                Ada.Text_IO.Put_Line
                   ("        Error in input file format:  Missing
closing ';' on table spec.");
                temp := null;
            end if;
        else
            Ada.Text_IO.Put_Line
               ("        Error in input file format:  Missing closing
')' on table spec.");
            temp := null;
        end if;

        return temp.all;

    end parsetable;

    ---------------------------
    --    parseAttributes    --
    ---------------------------
    function parseattributes return attribute_array_ptr is
        eof     : Boolean             := False;
        char    : Character;
        attribs : attribute_array_ptr := null;
        swap    : attribute_array_ptr := null;
        i       : Integer             := 1;
    begin
        eatWhite (file, eof);

        if not eof then
            Ada.Text_IO.Look_Ahead (file, char, eof);
        else
            raise Ada.IO_Exceptions.End_Error;
        end if;

        --at this point we should be ready to read the attribute name.
        if not eof and char /= Right_Parenthesis then
            Ada.Text_IO.Look_Ahead (file, char, eof);
        else
            Ada.Text_IO.Put_Line ("            found eof prematurely
or ')' is in wrong place.");
            raise Ada.IO_Exceptions.End_Error;
        end if;

        swap := new attribute_array (1 .. max_columns);

        while char /= Right_Parenthesis and char /= Semicolon and not
eof loop
            swap (i) := new attribute'class'(parseattribute);
            i        := i + 1;
            eatWhite (file, eof);

            if not eof and char /= Right_Parenthesis then
                --we are expecting a ')' or a comma.
                Ada.Text_IO.Look_Ahead (file, char, eof);
            else
                raise Ada.IO_Exceptions.End_Error;
            end if;

            if char /= Comma and char /= Right_Parenthesis and not eof
then
                Ada.Text_IO.Put_Line
                   ("            Error in input file:  Missing comma
between attributes.");
                eof  := True;
                swap := null;
            elsif not eof then
                --read the comma or the ')'
                Ada.Text_IO.Get (file, char);
            end if;

            eatWhite (file, eof);

            if eof then
                Ada.Text_IO.Put_Line ("Missing semi-colon or other
format error.");
                raise Ada.IO_Exceptions.End_Error;
            end if;

        end loop;

        i := i - 1;

        if i < 1 then
            swap := null;
        else
            attribs := new attribute_array (1 .. i);

            for x in  1 .. i loop
                attribs (x) := swap (x);
            end loop;

            swap := null;

        end if;

        return attribs;

    end parseattributes;

    --------------------------
    --    parseAttribute    --
    --------------------------
    function parseattribute return attribute'class is
        temp         : attribute_types.attribute_ptr;
        eof          : Boolean := False;
        char         : Character;
        aname        : String (1 .. max_attributename_length);
        atype        : String (1 .. max_typename_length);
        asize        : Integer;
        isprimarykey : Boolean := False;
        i            : Integer := 1;
    begin

        if not eof then
            Ada.Text_IO.Look_Ahead (file, char, eof);
        else
            raise Ada.IO_Exceptions.End_Error;
        end if;

        while char /= Space and
              char /= HT and
              char /= LF and
              char /= CR and
              char /= Left_Parenthesis and
              char /= Colon and
              not eof
        loop
            Ada.Text_IO.Get (file, char);
            aname (i) := char;
            i         := i + 1;
            Ada.Text_IO.Look_Ahead (file, char, eof);
        end loop;

        for x in  i .. max_attributename_length loop
            aname (x) := ' ';
        end loop;

        --at this point we have the attribute name.  Read white space
to
        --a parenthesis or an colon.
        eatWhite (file, eof);

        if not eof then
            Ada.Text_IO.Look_Ahead (file, char, eof);
        else
            raise Ada.IO_Exceptions.End_Error;
        end if;

        --the next character should be '(' or ':'
        if char = Left_Parenthesis then
            Ada.Text_IO.Get (file, char);
            eatWhite (file, eof);

            i := 1;

            --read "primary"
            while char /= Space and
                  char /= HT and
                  char /= LF and
                  char /= CR and
                  char /= Right_Parenthesis and
                  not eof
            loop
                Ada.Text_IO.Get (file, char);
                atype (i) := char;
                i         := i + 1;
                Ada.Text_IO.Look_Ahead (file, char, eof);
            end loop;

            for x in  i .. max_typename_length loop
                atype (x) := ' ';
            end loop;

            if Trim (atype, Ada.Strings.Both) = "PRIMARY" then
                isprimarykey := True;
            end if;

            eatWhite (file, eof);

            if not eof then
                Ada.Text_IO.Look_Ahead (file, char, eof);
            else
                raise Ada.IO_Exceptions.End_Error;
            end if;

            i := 1;

            --read "key"
            while char /= Space and
                  char /= HT and
                  char /= LF and
                  char /= CR and
                  char /= Right_Parenthesis and
                  not eof
            loop
                Ada.Text_IO.Get (file, char);
                atype (i) := char;
                i         := i + 1;
                Ada.Text_IO.Look_Ahead (file, char, eof);
            end loop;

            for x in  i .. max_typename_length loop
                atype (x) := ' ';
            end loop;

            if Trim (atype, Ada.Strings.Both) = "KEY" then
                isprimarykey := True;
            else
                isprimarykey := False;
            end if;

            eatWhite (file, eof);

            if not eof then
                Ada.Text_IO.Look_Ahead (file, char, eof);
            else
                raise Ada.IO_Exceptions.End_Error;
            end if;

            if char = ')' then
                Ada.Text_IO.Get (file, char);
            else
                Ada.Text_IO.Put_Line
                   ("            Error in input:  Missing ')' after
Primary Key designation.");
            end if;

            eatWhite (file, eof);

            if not eof then
                Ada.Text_IO.Look_Ahead (file, char, eof);
            else
                raise Ada.IO_Exceptions.End_Error;
            end if;

        end if;

        if char = Colon then
            Ada.Text_IO.Get (file, char);

            eatWhite (file, eof);

            if not eof then
                Ada.Text_IO.Look_Ahead (file, char, eof);
            else
                raise Ada.IO_Exceptions.End_Error;
            end if;

            i := 1;

            --read the type of the attribute into atype variable
            while char /= Space and
                  char /= HT and
                  char /= LF and
                  char /= CR and
                  char /= Comma and
                  char /= Left_Parenthesis and
                  char /= Right_Parenthesis and
                  char /= Semicolon and
                  not eof
            loop
                Ada.Text_IO.Get (file, char);
                atype (i) := char;
                i         := i + 1;
                Ada.Text_IO.Look_Ahead (file, char, eof);
            end loop;

            for x in  i .. max_typename_length loop
                atype (x) := ' ';
            end loop;

            eatWhite (file, eof);

            --read the left parenthesis
            if not eof and
               char = Left_Parenthesis and
               Trim (atype, Ada.Strings.Both) = "STRING"
            then
                Ada.Text_IO.Get (file, char);
                Ada.Text_IO.Look_Ahead (file, char, eof);
            elsif not eof and
                  char /= Left_Parenthesis and
                  Trim (atype, Ada.Strings.Both) = "STRING"
            then
                Ada.Text_IO.Put_Line ("            Incorrect syntax:
missing (size) for string.");
            elsif eof then
                raise Ada.IO_Exceptions.End_Error;
            end if;

            eatWhite (file, eof);

            if not eof then
                Ada.Text_IO.Look_Ahead (file, char, eof);
            else
                raise Ada.IO_Exceptions.End_Error;
            end if;

            --read the size of the type of the attribute into atype
variable
            while char /= Space and
                  char /= HT and
                  char /= LF and
                  char /= CR and
                  char /= Comma and
                  char /= Right_Parenthesis and
                  char /= Left_Parenthesis and
                  not eof
            loop

                Ada.Integer_Text_IO.Get (file, asize, 0);
                Ada.Text_IO.Look_Ahead (file, char, eof);
            end loop;

            --I have to do this temporarily to get this program
            --to work.  ALL strings are the same length.  The reason
            --is because there is no way to know how long the string
is
            --when serializing it in from a file (see loadtable in
            --schema_types) before we serialize it so that we can
            --provide a length discriminant to the type defined in
            --attribute_types.  So, we just make them all the same
            --length.
            asize := max_stringlength;

            eatWhite (file, eof);

            --read the right parenthesis
            if not eof and
               char = Right_Parenthesis and
               Trim (atype, Ada.Strings.Both) = "STRING"
            then
                Ada.Text_IO.Get (file, char);
                Ada.Text_IO.Look_Ahead (file, char, eof);
            elsif not eof and
                  char /= Right_Parenthesis and
                  Trim (atype, Ada.Strings.Both) = "STRING"
            then
                Ada.Text_IO.Put_Line
                   ("            Incorrect syntax:  missing (size ~)~
for string.");
            elsif eof then
                raise Ada.IO_Exceptions.End_Error;
            end if;

            eatWhite (file, eof);

            if Trim (atype, Ada.Strings.Both) = "BOOLEAN" then

                temp        := new booleanattribute;
                temp.name   := aname;
                temp.domain := atype;

                if isprimarykey then
                    temp.isprimarykey := True;
                end if;

            elsif Trim (atype, Ada.Strings.Both) = "STRING" then

                temp        := new stringattribute;
                temp.name   := aname;
                temp.domain := atype;

                if isprimarykey then
                    temp.isprimarykey := True;
                end if;

            elsif Trim (atype, Ada.Strings.Both) = "INTEGER" then

                temp        := new integerattribute;
                temp.name   := aname;
                temp.domain := atype;

                if isprimarykey then
                    temp.isprimarykey := True;
                end if;

            elsif Trim (atype, Ada.Strings.Both) = "DATE" then

                temp        := new dateattribute;
                temp.name   := aname;
                temp.domain := atype;

                if isprimarykey then
                    temp.isprimarykey := True;
                end if;

            else
                Ada.Text_IO.Put_Line ("            unknown type
specified.");
            end if;

            --after eating the white space we should be left at the
',' or
            --the ')'.
            eatWhite (file, eof);

            if not eof then
                Ada.Text_IO.Look_Ahead (file, char, eof);
            else
                raise Ada.IO_Exceptions.End_Error;
            end if;

            --we leave the comma in the stream so that parseAttributes
can
            --pick it up and loop for the next attribute.  We leave
the second
            --')' for parseAttributes to read to know when to exit the
loop and
            --quit parsing attributes.
            if char /= Comma and char /= Right_Parenthesis then
                Ada.Text_IO.Put_Line(
"            Error in input:  Missing ')' after Primary Key
designation or ',' between attributes.")
;
                temp := null;
            end if;

        else
            Ada.Text_IO.Put_Line
               (
"            Error in input file:  Format not correct, no type
specified for attribute " &
                aname);
            temp := null;
        end if;

        return temp.all;

    end parseattribute;

begin

    null;

end parser;


with Ada.Text_IO, Ada.Characters.Latin_1, Ada.Strings.Fixed,
Ada.Strings.Maps, Ada.IO_Exceptions;

use Ada.Characters.Latin_1;

package util is
    type string_ptr is access all String;
    type string_array is array (Integer range <>) of string_ptr;
    type string_array_ptr is access all string_array;

    max_columns              : Integer := 5;
    max_tables               : Integer := 5;
    max_tablename_length     : Integer := 25;
    max_attributename_length : Integer := 25;
    max_stringlength         : Integer := 255;
    max_typename_length      : Integer := 7;
    max_filename_length      : Integer := 45;
    max_index_namelength: integer := 50;

    procedure cls;
    procedure pl (text : in String; newline : in Boolean; setcolumn :
in Boolean := True);
    function tokenize (text : in String) return string_array_ptr;
    procedure eatWhite (fin : in out Ada.Text_IO.File_Type; eof : in
out Boolean);
end util;


package body Util is

    procedure cls is
        i : Integer := 1;
    begin
        while i < 40 loop
            Ada.Text_IO.New_Line;
            i := i + 1;
        end loop;
    end cls;

    procedure pl (text : in String; newline : in Boolean; setcolumn :
in Boolean := True) is
    begin

        if newline then
            if setcolumn then
                Ada.Text_IO.Set_Col (15);
            end if;
            Ada.Text_IO.Put_Line (text);
        elsif setcolumn then
            Ada.Text_IO.Set_Col (15);
            Ada.Text_IO.Put (text);
        else
            Ada.Text_IO.Put (text);
        end if;

    end pl;

    function tokenize (text : in String) return string_array_ptr is
        temp             : string_array_ptr;
        first            : Integer := 1;
        i                : Integer := 1;
        number_of_commas : Integer := 0;
        data             : string_ptr;
        data2            : string_ptr;
    begin
        data             := new String'(text);
        number_of_commas := Ada.Strings.Fixed.Count (data.all,
Ada.Strings.Maps.To_Set (','));

        if number_of_commas > max_columns then
            pl ("Invalid number of columns specified", True);
            raise Ada.IO_Exceptions.Data_Error;
        end if;

        temp := new string_array (1 .. number_of_commas + 1);

        --first will point to the first comma.
        first :=
            Ada.Strings.Fixed.Index
               (data.all,
                Ada.Strings.Maps.To_Set (','),
                Ada.Strings.Inside,
                Ada.Strings.Forward);

        while i <= number_of_commas and number_of_commas < max_columns
loop

            temp.all (i) := new String'(data.all (1 .. first - 1));
            data2        := new String (1 .. data.all'length - first);
            data2.all    := data.all (first + 1 .. data.all'length);
            data         := new String'(data2.all);
            i            := i + 1;
            first        :=
                Ada.Strings.Fixed.Index
                   (data.all,
                    Ada.Strings.Maps.To_Set (','),
                    Ada.Strings.Inside,
                    Ada.Strings.Forward);

        end loop;

        temp.all (i) := new String'(data.all);

        return temp;
    end tokenize;

    --------------------
    --    eatWhite    --
    --------------------
    procedure eatWhite (fin : in out Ada.Text_IO.File_Type; eof : in
out Boolean) is
        char : Character;
    begin

        Ada.Text_IO.Look_Ahead (fin, char, eof);

        while Ada.Text_IO.End_Of_Line (fin) and not
Ada.Text_IO.End_Of_File (fin) loop
            Ada.Text_IO.Skip_Line (fin);
        end loop;

        Ada.Text_IO.Look_Ahead (fin, char, eof);

        while (char = Space or char = HT or char = LF or char = CR)
and
              not Ada.Text_IO.End_Of_File (fin)
        loop

            Ada.Text_IO.Get (fin, char);

            while Ada.Text_IO.End_Of_Line (fin) and not
Ada.Text_IO.End_Of_File (fin) loop
                Ada.Text_IO.Skip_Line (fin);
            end loop;

            Ada.Text_IO.Look_Ahead (fin, char, eof);
        end loop;

    end eatWhite;

begin
    null;
end Util;


with util, Ada.Calendar, attribute_types, Ada.Streams.Stream_IO;

use util, attribute_types;

package schema_types is

    ---------------------------------
    --    Variable Declarations    --
    ---------------------------------
    fin  : Ada.Streams.Stream_IO.File_Type;
    fout : Ada.Streams.Stream_IO.File_Type;

    type schema (number_of_attributes : Integer) is tagged record
        tablename : String (1 .. max_tablename_length) := (1 ..
max_tablename_length => ' ');
        attributes        : attribute_array (1 ..
number_of_attributes);
        byte_start        : Integer := 0;
        byte_end          : Integer := 0;
        primary_key_count : Integer := 0;
    end record;
    type schema_ptr is access all schema'class;
    type schema_array is array (Integer range <>) of schema_ptr;
    type schema_array_ptr is access all schema_array;
    type tuple is array (Integer range <>) of attribute_array_ptr;
    type tuple_ptr is access all tuple;

    procedure createtable (schemainfo : schema_ptr);
    function loadtable (sname : String) return schema_ptr;
    function findrecord (schemainfo : schema; values :
attribute_array) return Integer;
    procedure insertrec (schemainfo : schema; values :
attribute_array);
    procedure deleterec (schemainfo : schema; primary_key_values :
attribute_array);
    procedure updaterec
       (schemainfo : schema;
        pkattribs  : attribute_array;
        values     : attribute_array);
    function selectrec (schemainfo : schema) return tuple_ptr;

end schema_types;


with Ada.Streams.Stream_IO, Ada.Calendar, GNAT.Calendar.Time_IO,
Ada.Text_IO, Ada.Strings.Fixed,
 Ada.Directories, Ada.IO_Exceptions;
use Ada.Streams.Stream_IO, Ada.Calendar, GNAT.Calendar.Time_IO,
Ada.Strings.Fixed;

package body schema_types is

    procedure createtable (schemainfo : schema_ptr) is
        fout     : File_Type;
        attribs  : attribute_array_ptr;
        attribs2 : attribute_array_ptr;
        i        : Integer := 1;
        ii       : Integer := 1;
        temp     : access attribute'class;
    begin

        if schemainfo = null then
            return;
        end if;

        --  put them in order first
        for x in  1 .. schemainfo.attributes'length loop
            for y in  x + 1 .. schemainfo.attributes'length loop

                if schemainfo.attributes (y).name <
schemainfo.attributes (x).name then
                    temp                      := schemainfo.attributes
(y);
                    schemainfo.attributes (y) := schemainfo.attributes
(x);
                    schemainfo.attributes (x).all := temp.all;
                end if;
            end loop;
        end loop;

        attribs  := new attribute_array (1 ..
schemainfo.attributes'length);
        attribs2 := new attribute_array (1 ..
schemainfo.attributes'length);

        for x in  1 .. schemainfo.attributes'length loop
            if schemainfo.attributes (x).isprimarykey then
                attribs (i) := schemainfo.attributes (x);
                i           := i + 1;
            else
                attribs2 (ii) := schemainfo.attributes (x);
                ii            := ii + 1;
            end if;
        end loop;

        i  := i - 1;
        ii := ii - 1;

        --  the primary_key attributes first
        for x in  1 .. i loop
            schemainfo.attributes (x) := attribs (x);
        end loop;

        --  non-primary key attributes next
        for x in  1 .. ii loop
            schemainfo.attributes (x + i) := attribs2 (x);
        end loop;

        Create (fout, Out_File, Trim (schemainfo.all.tablename,
Ada.Strings.Both));
        --We are writing the number of attributes so that when we load
        --the table we can determine the number of attributes to put
        --into the new, loading schema.
        Integer'write (Stream (fout),
schemainfo.all.attributes'length);

        schemainfo.all.byte_start := Integer'val (Index (fout));

	--we output it once so that we can capture the file position for
byte_end
        schema'output (Stream (fout), schemainfo.all);

	--fill in byte_end
        schemainfo.all.byte_end := Integer'val (Index (fout));

	close(fout);
	Open (fout, Out_File, Trim (schemainfo.all.tablename,
Ada.Strings.Both));

        Integer'write (Stream (fout),
schemainfo.all.attributes'length);

	--now we have byte_start and byte_end
        schema'output (Stream (fout), schemainfo.all);

        for x in  1 .. schemainfo.all.attributes'length loop
	    to_disc(fout, schemainfo.all.attributes(x).all);
        end loop;

        Close (fout);

    end createtable;

    function loadtable (sname : String) return schema_ptr is
        schemainfo : schema_ptr;
        fin        : File_Type;
        length     : Integer;
        position   : integer;
    begin
        Open (fin, In_File, Trim (sname, Ada.Strings.Both));

        Integer'read (Stream (fin), length);

        schemainfo                := new schema (length);
        schemainfo.all            := schema'class'input (Stream
(fin));

	--mark where we are at in the file to start reading attributes.
        position                  := Integer'val (Index (fin));

        for x in  1 .. schemainfo.attributes'length loop
-----------------------------------------------------
-- Old code I plan on removing
-----------------------------------------------------
--              schemainfo.all.attributes (x).all.byte_start :=
position;
--
--              if Trim (schemainfo.all.attributes (x).domain,
Ada.Strings.Both) = "BOOLEAN" then
--  		schemainfo.all.attributes (x)                := new
booleanattribute;
--                  schemainfo.all.attributes (x).all            :=
--                      booleanattribute'input (Stream (fin));
--              elsif Trim (schemainfo.all.attributes (x).domain,
Ada.Strings.Both) = "STRING" then
--                  schemainfo.all.attributes (x)                :=
new stringattribute;
--                  schemainfo.all.attributes (x).all            :=
--                      stringattribute'input (Stream (fin));
--              elsif Trim (schemainfo.all.attributes (x).domain,
Ada.Strings.Both) = "INTEGER" then
--                  schemainfo.all.attributes (x)                :=
new integerattribute;
--                  schemainfo.all.attributes (x).all            :=
--                      integerattribute'input (Stream (fin));
--              else --  "DATE"
--                  schemainfo.all.attributes (x)                :=
new dateattribute;
--                  schemainfo.all.attributes (x).all            :=
--                      dateattribute'input (Stream (fin));
--              end if;
--              position := Integer'val (Index (fin));
--              schemainfo.all.attributes (x).all.byte_end   :=
position;
-- End old code
------------------------------------------------------
-----------------------------------------------------------
-- The code I want to use for dispatching
-----------------------------------------------------------
--  	    schemainfo.all.attributes (x) := new
attribute'class'(from_disc(fin, schemainfo.all.attributes (x).all));
-----------------------------------------------------------

------------------------------------------------------------
-- Debug code below --
------------------------------------------------------------
-- For some reason some of the attributes on schemainfo come through
-- as "unknown" after the schemainfo was filled in from
'input(stream).
-- It doesn't appear to me that createtable procedure in this package
-- writes the schema object incorrectly so I don't understand why
-- the attributes of the schemainfo object we retrieve with 'input are
-- "unknown".  Well, the domain member of the attribute is not one of
-- BOOLEAN, STRING, INTEGER or DATE; that's why it prints it but why
-- isn't the domain member one of those values?

            if Trim (schemainfo.all.attributes (x).domain,
Ada.Strings.Both) = "BOOLEAN" then
ada.text_io.put_line(schemainfo.all.attributes (x).name);
ada.text_io.put_line(schemainfo.all.attributes (x).domain);

            elsif Trim (schemainfo.all.attributes (x).domain,
Ada.Strings.Both) = "STRING" then
ada.text_io.put_line(schemainfo.all.attributes (x).name);
ada.text_io.put_line(schemainfo.all.attributes (x).domain);

	    elsif Trim (schemainfo.all.attributes (x).domain,
Ada.Strings.Both) = "INTEGER" then
ada.text_io.put_line(schemainfo.all.attributes (x).name);
ada.text_io.put_line(schemainfo.all.attributes (x).domain);

            elsif Trim (schemainfo.all.attributes (x).domain,
Ada.Strings.Both) = "DATE" then
ada.text_io.put_line(schemainfo.all.attributes (x).name);
ada.text_io.put_line(schemainfo.all.attributes (x).domain);
	    else
ada.text_io.put_line("unknown");
            end if;
        end loop;

-- End Debug Code
---------------------------------------------------------------
        Close (fin);

        return schemainfo;

    exception
        when Ada.IO_Exceptions.Status_Error =>
            Ada.Text_IO.Put_Line ("Status error in loadtable");
            return null;
    end loadtable;

    ---------------------
    --  INSERT RECORD  --
    ---------------------
    procedure insertrec (schemainfo : schema; values :
attribute_array) is
        location : Integer := -1;
        char     : Character;
    begin

        location := findrecord (schemainfo, values);

        --if the record isn't in there it is -1
        if location = -1 then

            Open (fout, Append_File, Trim (schemainfo.tablename,
Ada.Strings.Both));

            for x in  1 .. schemainfo.attributes'length loop
		to_disc(fout, values (x).all);
            end loop;

            Close (fout);
        else
            pl ("Record already exists with that key", True, True);
            pl ("Press Enter to continue...", True, True);
            Ada.Text_IO.Get_Immediate (char);
        end if;

    end insertrec;

    ---------------------
    --  SELECT RECORD  --
    ---------------------
    function selectrec (schemainfo : schema) return tuple_ptr is
        temp  : attribute_array_ptr;
        recs  : tuple_ptr;
        recs2 : tuple_ptr;
        i     : Integer := 1;

    begin
        Open (fin, In_File, Trim (schemainfo.tablename,
Ada.Strings.Both));
        Set_Index
           (fin,
            Ada.Streams.Stream_IO.Count'val
                (schemainfo.attributes
(schemainfo.attributes'length).all.byte_end));

        temp := new attribute_array (1 ..
schemainfo.attributes'length);

        if End_Of_File (fin) then
            Close (fin);
            return null;
        end if;

        recs := new tuple (1 .. 1);

        while not End_Of_File (fin) loop
            for x in  1 .. temp.all'length loop
		temp(x) := new attribute'class'(from_disc(fin, schemainfo.attributes
(x).all));
            end loop;

            if i < 2 then
                recs (recs'last) := temp;
            else
                recs2 := new tuple (1 .. recs'length);

                for z in  1 .. recs'length loop
                    recs2 (z) := recs (z);
                end loop;

                recs := new tuple (1 .. i);

                for z in  1 .. recs2'length loop
                    recs (z) := recs2 (z);
                end loop;

                recs (recs'last) := temp;
            end if;
            temp := new attribute_array (1 ..
schemainfo.attributes'length);
            i    := i + 1;
        end loop;

        Close (fin);

        return recs;

    end selectrec;

    -------------------
    --  FIND RECORD  --
    -------------------
    function findrecord (schemainfo : schema; values :
attribute_array) return Integer is
        temp         : attribute_array_ptr;
        location     : Ada.Streams.Stream_IO.Count;
        found        : Integer := 0;
        done         : Boolean := False;
        comparrisons : Integer := 0;
    begin

        Open (fin, In_File, Trim (schemainfo.tablename,
Ada.Strings.Both));

        Set_Index
           (fin,
            Ada.Streams.Stream_IO.Count'val
                (schemainfo.attributes
(schemainfo.attributes'length).all.byte_end));
        temp := new attribute_array (1 ..
schemainfo.attributes'length);

        while not End_Of_File (fin) and then not done loop
            --mark our current location in the file.
            location := Index (fin);

            --read the whole line from the file,
            for x in  1 .. schemainfo.attributes'length loop
		temp(x) := new attribute'class'(from_disc(fin,
schemainfo.attributes(x).all));
            end loop;

            --then compare them.
            comparrisons := 0;
            found        := 0;

            for x in  1 .. values'length loop

                if schemainfo.attributes (x).isprimarykey then

                    comparrisons := comparrisons + 1;

                    if Trim (values (x).domain, Ada.Strings.Both) =
"BOOLEAN" then
                        if booleanattribute (temp (x).all).value =
                           booleanattribute (values (x).all).value
                        then
                            found := found + 1;
                        end if;
                        --
ada.text_io.put_line(boolean'image(booleanattribute(temp(x).all).value
                        --));
                    elsif Trim (values (x).domain, Ada.Strings.Both) =
"STRING" then
                        if stringattribute (temp (x).all).value =
                           stringattribute (values (x).all).value
                        then
                            found := found + 1;
                        end if;
                        --
ada.text_io.put_line(stringattribute(temp(x).all).value);
                    elsif Trim (values (x).domain, Ada.Strings.Both) =
"INTEGER" then
                        if integerattribute (temp (x).all).value =
                           integerattribute (values (x).all).value
                        then
                            found := found + 1;
                        end if;
                        --
ada.text_io.put_line(integer'image(integerattribute(temp(x).all).value
                        --));
                    else -- "DATE"
                        if dateattribute (temp (x).all).value =
                           dateattribute (values (x).all).value
                        then
                            found := found + 1;
                        end if;
                        --
ada.text_io.put_line(image(dateattribute(temp(x).all).value,
                        --iso_date));
                    end if;
                end if;
            end loop;

            if found = comparrisons and then comparrisons > 0 then
                done := True;
            end if;

            if End_Of_File (fin) then
                done := True;
            end if;
        end loop;

        Close (fin);

        if found < comparrisons then
            return -1;
        elsif found = 0 and then comparrisons = 0 then
            return -1;
        else
            return Integer'val (location);
        end if;

    end findrecord;

    ---------------------
    --  DELETE RECORD  --
    ---------------------
    procedure deleterec (schemainfo : schema; primary_key_values :
attribute_array) is
        location          : Integer;
        original_byte_end : Integer := schemainfo.attributes
(schemainfo.attributes'last).byte_end;
        temp              : attribute_array_ptr;
        char              : Character;
    begin
        location := findrecord (schemainfo, primary_key_values);

        --If findrecord seeks past the schema info header in the file
and ends
        --on the end of file it will return -1.  Therefore, no records
to delete
        --in the file.
        if location = -1 then
            pl ("No records to delete with that key", True, True);
            pl ("Press Enter to continue...", True, True);
            Ada.Text_IO.Get_Immediate (char);
            return;
        end if;

        Create (fout, Out_File, "swapfile");
        Open (fin, In_File, Trim (schemainfo.tablename,
Ada.Strings.Both));

        --output the schema header information to the file
        Integer'write (Stream (fout), schemainfo.attributes'length);

	--I took these out so that we could create a function for
	--updating records that returns an rrn.  functions do not
	--allow out mode parameters and deleterec had an out mode
	--parameter because of this next line.
        --schemainfo.byte_start := Integer'val (Index (fout));
        schema'output (Stream (fout), schemainfo);

	--I took these out so that we could create a function for
	--updating records that returns an rrn.  functions do not
	--allow out mode parameters and deleterec had an out mode
	--parameter because of this next line.
        --schemainfo.byte_end := Integer'val (Index (fout));

        for x in  1 .. schemainfo.attributes'length loop

		to_disc(fout, schemainfo.attributes(x).all);
        end loop;

        --set the index on the input file so we skip the header on
input file.
        Set_Index (fin, Ada.Streams.Stream_IO.Count'val
(original_byte_end));
        temp := new attribute_array (1 ..
schemainfo.attributes'length);

        --Read records from one file and insert them into the other
file until
        --we get to the location of the record we want to delete.
        while Index (fin) < Ada.Streams.Stream_IO.Count'val (location)
loop

            for x in  1 .. temp.all'length loop
		temp(x) := new attribute'class'(from_disc(fin,
schemainfo.attributes(x).all));
		to_disc(fin, temp(x).all);
            end loop;
        end loop;

        --do a blank read to move past the line to delete
        for x in  1 .. schemainfo.attributes'length loop

	    temp(x) := new attribute'class'(from_disc(fin,
schemainfo.attributes(x).all));
        end loop;

	--output the rest of the records.
        while not End_Of_File (fin) loop
            for x in  1 .. temp.all'length loop
		temp(x) := new attribute'class'(from_disc(fin,
schemainfo.attributes(x).all));
		to_disc(fout, temp(x).all);
            end loop;
        end loop;

        Close (fin);
        Close (fout);
        Ada.Directories.Delete_File (Trim (schemainfo.tablename,
Ada.Strings.Both));
        Ada.Directories.Rename ("swapfile", Trim
(schemainfo.tablename, Ada.Strings.Both));

        location := findrecord (schemainfo, primary_key_values);

        if location >= 1 then
            deleterec (schemainfo, primary_key_values);
        end if;

    end deleterec;

    ---------------------
    --  UPDATE RECORD  --
    ---------------------
    procedure updaterec
       (schemainfo : schema;
        pkattribs  : attribute_array;
        values     : attribute_array)
    is
        position : Integer := 0;
        char     : Character;
    begin
        position := findrecord (schemainfo, pkattribs);

        --if the record doesn't exist then insert it
        if position < 1 then
            pl ("That record doesn't exist in the database.", True,
True);
            pl ("Insert it instead (menu item 1).", True, True);
            pl ("Press Enter to continue...", True, True);
            Ada.Text_IO.Get_Immediate (char);
        elsif position >= 1 then
            deleterec (schemainfo, pkattribs);
            insertrec (schemainfo, values);
        end if;
    end updaterec;

begin
    null;
end schema_types;


with util, Ada.Calendar, ada.streams.stream_io;

use util, Ada.Calendar, ada.streams.stream_io;

package attribute_types is

    -----------------------------------
    --    Forwarding Declarations    --
    -----------------------------------
    type attribute is abstract tagged;
    type booleanattribute is tagged;
    type integerattribute is tagged;
    type stringattribute is tagged;
    type dateattribute is tagged;

    --------------------------------------
    --    Attribute Type Declarations    --
    --------------------------------------
    type attribute is abstract tagged record
        name         : String (1 .. max_attributename_length) :=
           (1 .. max_attributename_length => ' ');
        domain       : String (1 .. max_typename_length) := (1 ..
max_typename_length => ' ');
        isprimarykey : Boolean                                :=
False;
        byte_start   : Integer                                := 0;
        byte_end     : Integer                                := 0;
    end record;

    --------------------------------------
    --    Basic Pointer Declarations    --
    --------------------------------------
    type attribute_ptr is access attribute'class;
    type attribute_array is array (Integer range <>) of access
attribute'class;
    type attribute_array_ptr is access all attribute_array;

    procedure to_disc (fout: file_type; item: in out attribute) is
abstract;
    function from_disc(fout: file_type; item: attribute) return
attribute'class is abstract;


    -----------------------------------
    --    Extended Attribute Types   --
    -----------------------------------
    type booleanattribute is new attribute with record
        value : Boolean := False;
    end record;
    type booleanattribute_ptr is access all booleanattribute'class;
    procedure to_disc (fout: file_type; item: in out
booleanattribute);
    function from_disc(fin: file_type; item: booleanattribute) return
attribute'class;

    type integerattribute is new attribute with record
        value : Integer := 0;
    end record;
    type integerattribute_ptr is access all integerattribute'class;
    procedure to_disc (fout: file_type; item: in out
integerattribute);
    function from_disc(fin: file_type; item: integerattribute) return
attribute'class;

    type stringattribute is new attribute with record
        value : String (1 .. max_stringlength) := (1 ..
max_stringlength => ' ');
    end record;
    type stringattribute_ptr is access all stringattribute'class;
    procedure to_disc (fout: file_type; item: in out stringattribute);
    function from_disc(fin: file_type; item: stringattribute) return
attribute'class;

    type dateattribute is new attribute with record
        year  : Year_Number  := 1901;
        month : Month_Number := 1;
        day   : Day_Number   := 1;
        value : Time         := Time_Of (1901, 1, 1);
    end record;
    type dateattribute_ptr is access all dateattribute'class;
    procedure to_disc (fout: file_type; item: in out dateattribute);
    function from_disc(fin: file_type; item: dateattribute) return
attribute'class;

end attribute_types;


with ada.text_io, util, ada.calendar;
use util, ada.calendar;

package body attribute_types is

    procedure to_disc (fout: file_type; item: in out booleanattribute)
is
    begin
        item.byte_start := Integer'val (Index (fout));
        item.byte_end := Integer'val (Index (fout)) +
(booleanattribute'size / 8) - 7;
        booleanattribute'class'output(Stream(fout), item);
    end to_disc;

    function from_disc(fin: file_type; item: booleanattribute) return
attribute'class is
        temp : access attribute'class;
    begin
      temp := new booleanattribute;
      temp.all := booleanattribute'class'input (Stream (fin));
      return temp.all;
    end from_disc;

    procedure to_disc (fout: file_type; item: in out integerattribute)
is
    begin
        item.byte_start := Integer'val (Index (fout));
        item.byte_end := Integer'val (Index (fout)) +
(integerattribute'size / 8) - 7;
        integerattribute'class'output(Stream(fout), item);
    end to_disc;

    function from_disc(fin: file_type; item: integerattribute) return
attribute'class is
    	temp : access attribute'class;
    begin
  	temp := new integerattribute;
	temp.all := integerattribute'class'input (Stream (fin));
	return temp.all;
    end from_disc;

    procedure to_disc (fout: file_type; item: in out stringattribute)
is
    begin
        item.byte_start := Integer'val (Index (fout));
        item.byte_end := Integer'val (Index (fout)) +
(stringattribute'size / 8) - 7;
        stringattribute'class'output(Stream(fout), item);
    end to_disc;

    function from_disc(fin: file_type; item: stringattribute) return
attribute'class is
    	temp: access attribute'class;
    begin
  	temp := new stringattribute;
	temp.all := stringattribute'class'input (Stream (fin));
	return temp.all;
    end from_disc;

    procedure to_disc (fout: file_type; item: in out dateattribute) is
    begin
        item.byte_start := Integer'val (Index (fout));
        item.byte_end := Integer'val (Index (fout)) +
(dateattribute'size / 8) - 11;
        dateattribute'class'output(Stream(fout), item);
    end to_disc;

    function from_disc(fin: file_type; item: dateattribute) return
attribute'class is
    	temp: access attribute'class;
    begin
    	temp := new dateattribute;
	temp.all := dateattribute'class'input (Stream (fin));
	return temp.all;
    end from_disc;

begin
    null;
end attribute_types;


with Ada.Streams.Stream_IO, util, attribute_types,Ada.Calendar; use
util, attribute_types,Ada.Calendar;

package index_types is

    ---------------------------------
    --    Variable Declarations    --
    ---------------------------------
    fin  : Ada.Streams.Stream_IO.File_Type;
    fout : Ada.Streams.Stream_IO.File_Type;
--------------------------------------------------------
--  THIS FILE IS NOT COMPLETE NOR USED YET!!!
--  IT IS INCLUDED BECAUSE IT IS WITH'D
--------------------------------------------------------
    --an index is a file
    --it contains the primary key value and file position for the
primary key for a primary index
	    --the spec sounds like only one attribute will make up a primary
key.
    --for a secondary index it contains an attribute and a position.
	    --The spec says only one attribute.
    --primary indexes are named after the table it belongs to
<tablename>_PIDX
    --secondary indexes are named after the table it belongs to like
<tablename>_SIDX

    --each schema object has a list of index names for a table
	    --initially the list of index names is empty
    --the user adds an index to the table and then the index name goes
into the list of indexes on
    --the schema
    --the schema information will have to be re-written to the table
file when an index is added.
	    --This is the same for the secondary indexes
    --if a tuple that an index is based on is inserted, deleted or
updated then the index must be
    --loaded and re-created.
    ----on updates we only have to change the index if the index value
is being changed.

--The attributes store the name of an index on itself.  When we load
the schema
--we go through each attribute and determine if it is indexed then
load that
--index if it is.  This gives us the "type" on the index value,
elleviates the
--need to maintain a list of index names in the schema object,
----what do we load an index into?


    --There are two types of indexes: primary and secondary
    --** note ** the primary index is just like the secondary; it only
has one entry per item
    --because there is only
    --one item allowed per entry due to the fact that primary keys are
unique.
    --The differences in indexes are:
    ----if we remove a value from a secondary we must match the rrn to
remove the correct
    --item; with a primary key there is only one to remove.
    ----when finding a record, with a primary index when we find the
value we don't
    ----have to search a bunch of records for the exact tuple match.
With secondary
    ----, because there are multiple values that are the same with
different rrn's
    ----we have to search each rrn and compare values to match the
tuple.

    --we don't sort as we read the table, we read the table and then
sort the index file.

    type index is abstract tagged record
        filename : String (1 .. max_index_namelength);
        rrn  : Ada.Streams.Stream_IO.Count := 0;
    end record;
    type index_ptr is access all index;
    type index_array is array (Integer range <>) of index_ptr;

    type booleanindex is tagged record
        key : boolean;
    end record;

    type integerindex is tagged record
        key : integer;
    end record;

    type stringindex is tagged record
        key : string(1..max_stringlength);
    end record;

    type dateindex is tagged record
        key : time;
    end record;
end index_types;


*************************
* Contents of the table.txt file
* This file is used by the main procedure dbprog.
* It must be labeled tables.txt and placed in the
* same directory as the executable dbprog.exe
*************************
T3(
ID(PRIMARY KEY):INTEGER
);

T2(
DATA(PRIMARY KEY):STRING(15)
);

T4(
II(PRIMARY KEY):DATE
);

T1(
mine(PRIMARY KEY):BOOLEAN
);
*************************




^ permalink raw reply	[relevance 1%]

* STORAGE_ERROR : EXCEPTION_STACK_OVERFLOW
@ 2007-04-02  6:13  1% andrew.carroll
                     ` (2 more replies)
  0 siblings, 3 replies; 200+ results
From: andrew.carroll @ 2007-04-02  6:13 UTC (permalink / raw)


I read the messages earlier on this error where they were working on
some medical device.  My program is not threaded.  I'm not real sure
where to put a pragma storage_size(...) statement.  Does it go inside
the procedure of the main program?  Does it go in the package header?
The package body?  Where should I put it?  Okay, you caught me, I
tried all of those and the compiler wouldn't let me put them there.
How do I use heap instead when allocating an object?  Is it some other
word than "new" or just a pragma?

I didn't have trouble with this until I started using 'class types
instead of _ptr "types".  I am trying to use ada.streams.stream_io
with dispatching.  I wasn't using dispatching originally.  In the
newest version, with dispatching, I made my base type abstract,
changed from using _ptr "types" to 'class types and then I would get
the message "raised PROGRAM_ERROR : EXCEPTION_ACCESS_VIOLATION".  So I
kept converting things from _ptr to 'class thinking that maybe a tag
wasn't written or that it was due to some inconsistency between
'outputing an _ptr and 'inputing a 'class.

I tracked it down to one section of my code that uses 'input to read
the object from a file stream.  After it is 'inputed the data is all
messed up.  The section of code is where I capture the return value of
the return value of the call to from_disc (which is a dispatched
call).  Anyway, now that I've muddied that up.  HELP!

Here are the base types and all that:

with util, Ada.Calendar, ada.streams.stream_io;

use util, Ada.Calendar, ada.streams.stream_io;

package attribute_types is

    -----------------------------------
    --    Forwarding Declarations    --
    -----------------------------------
    type attribute is abstract tagged;
    type booleanattribute is tagged;
    type integerattribute is tagged;
    type stringattribute is tagged;
    type dateattribute is tagged;

    --------------------------------------
    --    Attribute Type Declarations    --
    --------------------------------------
    type attribute is abstract tagged record
        name         : String (1 .. max_attributename_length) :=
           (1 .. max_attributename_length => ' ');
        domain       : String (1 .. max_typename_length) := (1 ..
max_typename_length => ' ');
        isprimarykey : Boolean                                :=
False;
        byte_start   : Integer                                := 0;
        byte_end     : Integer                                := 0;
    end record;

    --------------------------------------
    --    Basic Pointer Declarations    --
    --------------------------------------
    type attribute_ptr is access attribute'class;
    --type attribute_array is array (Integer range <>) of
attribute_ptr;
    type attribute_array is array (Integer range <>) of access
attribute'class;
    type attribute_array_ptr is access all attribute_array;

    procedure to_disc (fout: file_type; item: in out attribute) is
abstract;
    function from_disc(fout: file_type; item: attribute) return
attribute'class is abstract;


    -----------------------------------
    --    Extended Attribute Types   --
    -----------------------------------
    type booleanattribute is new attribute with record
        value : Boolean := False;
    end record;
    type booleanattribute_ptr is access all booleanattribute'class;
    procedure to_disc (fout: file_type; item: in out
booleanattribute);
    function from_disc(fin: file_type; item: booleanattribute) return
attribute'class;

    type integerattribute is new attribute with record
        value : Integer := 0;
    end record;
    type integerattribute_ptr is access all integerattribute'class;
    procedure to_disc (fout: file_type; item: in out
integerattribute);
    function from_disc(fin: file_type; item: integerattribute) return
attribute'class;

    type stringattribute is new attribute with record
        value : String (1 .. max_stringlength) := (1 ..
max_stringlength => ' ');
    end record;
    type stringattribute_ptr is access all stringattribute'class;
    procedure to_disc (fout: file_type; item: in out stringattribute);
    function from_disc(fin: file_type; item: stringattribute) return
attribute'class;

    type dateattribute is new attribute with record
        year  : Year_Number  := 1901;
        month : Month_Number := 1;
        day   : Day_Number   := 1;
        value : Time         := Time_Of (1901, 1, 1);
    end record;
    type dateattribute_ptr is access all dateattribute'class;
    procedure to_disc (fout: file_type; item: in out dateattribute);
    function from_disc(fin: file_type; item: dateattribute) return
attribute'class;

end attribute_types;


with ada.text_io, util, ada.calendar;
use util, ada.calendar;

package body attribute_types is

    procedure to_disc (fout: file_type; item: in out booleanattribute)
is
    begin
        item.byte_start := Integer'val (Index (fout));
        item.byte_end := Integer'val (Index (fout)) +
(booleanattribute'size / 8) - 7;
        booleanattribute'class'output(Stream(fout), item);
    end to_disc;

    function from_disc(fin: file_type; item: booleanattribute) return
attribute'class is
        temp : access attribute'class;
    begin
      temp := new booleanattribute;
      temp.all := booleanattribute'class'input (Stream (fin));
      return temp.all;
    end from_disc;

    procedure to_disc (fout: file_type; item: in out integerattribute)
is
    begin
        item.byte_start := Integer'val (Index (fout));
        item.byte_end := Integer'val (Index (fout)) +
(integerattribute'size / 8) - 7;
        integerattribute'class'output(Stream(fout), item);
    end to_disc;

    function from_disc(fin: file_type; item: integerattribute) return
attribute'class is
    	temp : access attribute'class;
    begin
  	temp := new integerattribute;
	temp.all := integerattribute'class'input (Stream (fin));
	return temp.all;
    end from_disc;

    procedure to_disc (fout: file_type; item: in out stringattribute)
is
    begin
        item.byte_start := Integer'val (Index (fout));
        item.byte_end := Integer'val (Index (fout)) +
(stringattribute'size / 8) - 7;
        stringattribute'class'output(Stream(fout), item);
    end to_disc;

    function from_disc(fin: file_type; item: stringattribute) return
attribute'class is
    	temp: access attribute'class;
    begin
  	temp := new stringattribute;
	temp.all := stringattribute'class'input (Stream (fin));
	return temp.all;
    end from_disc;

    procedure to_disc (fout: file_type; item: in out dateattribute) is
    begin
        item.byte_start := Integer'val (Index (fout));
        item.byte_end := Integer'val (Index (fout)) +
(dateattribute'size / 8) - 11;
        dateattribute'class'output(Stream(fout), item);
    end to_disc;

    function from_disc(fin: file_type; item: dateattribute) return
attribute'class is
    	temp: access attribute'class;
    begin
    	temp := new dateattribute;
	temp.all := dateattribute'class'input (Stream (fin));
	return temp.all;
    end from_disc;

begin
    null;
end attribute_types;

with attribute_types...
use attribute_types...
package schema_types is
...
    type schema (number_of_attributes : Integer) is tagged record
        tablename : String (1 .. max_tablename_length) := (1 ..
max_tablename_length => ' ');

        --attribute order is always from left to right
        --Primary key attributes | others
        attributes        : attribute_array (1 ..
number_of_attributes);
        byte_start        : Integer := 0;
        byte_end          : Integer := 0;
        primary_key_count : Integer := 0;
    end record;
...
end schema_types;

Here is the code that initiates disaster:
schemainfo.all.attributes (x) := new attribute'class'(from_disc(fin,
schemainfo.all.attributes (x).all));




^ permalink raw reply	[relevance 1%]

* Re: Design help
    2007-03-09 23:07  2% ` Simon Wright
@ 2007-03-10 13:38  2% ` Ludovic Brenta
  1 sibling, 0 replies; 200+ results
From: Ludovic Brenta @ 2007-03-10 13:38 UTC (permalink / raw)


Andrew Carrol writes:
> I am trying to design (what I guess is) a database table adapter.  Yes,
> it is a master's course assignment.  The current design is to use a file
> and have one record per line.  My goal is to get each line to be
> "serialized" so I can read the whole line in bytes and then take chunks
> of it and "cast" those into objects.

The answer depends on whether or not your file contains fixed-width
records.  If that is the case, I would simply declare a record type
and use Sequential_IO for the record type directly, like e.g.

type Seconds_Since_Epoch is new Ada.Interfaces.Unsigned_32;

type DB_Record is record
   Primary_Key   : Ada.Interfaces.Unsigned_32;
   Name          : String (1 .. 20);
   Address       : String (1 .. 100);
   Date_Of_Birth : Seconds_Since_Epoch;
end record;

package DB_Record_IO is
   new Ada.Sequential_IO (Element_Type => DB_Record);

But if, on the other hand, the file contains variable-width records,
such as comma-separated values (CSV), you will need more sophisticated
conversion functions.  In that case, I would use Ada.Streams.Stream_IO
directly and convert the Stream_Elements one by one.

If you want to convert to objects of tagged types, you should provide
a constructor function for your tagged type, like so:

type T is tagged record ... end record;

function To_T (Raw_Bytes : in Ada.Streams.Stream_Element_Array)
   return T;

HTH

Note that the database file will probably not contain the tag itself.
OTOH, if it does, then you can just use streams.

-- 
Ludovic Brenta.



^ permalink raw reply	[relevance 2%]

* Re: Design help
  @ 2007-03-09 23:07  2% ` Simon Wright
  2007-03-10 13:38  2% ` Ludovic Brenta
  1 sibling, 0 replies; 200+ results
From: Simon Wright @ 2007-03-09 23:07 UTC (permalink / raw)


I think you should look at Ada.Streams and Ada.Streams.Stream_IO. OK,
this could do most of the work for you, but that's what higher-level
languages & their libraries are for ... not sure how your professor
would react.



^ permalink raw reply	[relevance 2%]

* My bug or compiler bug?
@ 2007-02-14 20:58  3% Anh Vo
  0 siblings, 0 replies; 200+ results
From: Anh Vo @ 2007-02-14 20:58 UTC (permalink / raw)


I could not understand why it, line 44 of the code below, compiles. I
strugged with the question why actual parameter R'(10.0, 20.0) matches
with access type parameter R_Pointer at line 15. Is it my bug or
compiler bug? Thanks.

AV

with Ada.Text_IO;            use Ada.Text_IO;
with Ada.Streams.Stream_IO;  use Ada.Streams;

procedure Stream_IO_Demo_Cutdown is -- This is the cutdown version of
example
                                    -- Stream_IO_Demo in GNAT-GPL-2006
   type R is record
      A : Float;
      B : Long_Float;
   end record;

   type R_Pointer is access all R;

   procedure Write_R_Pointer
      (Stream : access Ada.Streams.Root_Stream_Type'Class;
       Item   : in     R_Pointer);
   for R_Pointer'Write use Write_R_Pointer;

   procedure Write_R_Pointer
      (Stream : access Ada.Streams.Root_Stream_Type'Class;
       Item   : in     R_Pointer)
      --  Write a boolean flag indicating whether Item designates an
object.
      --  If Item designates an object we also write the value of that
object.
   is
   begin
      if Item = null then
         Boolean'Write (Stream, False);
      else
         Boolean'Write (Stream, True);
         R'Write (Stream, Item.all);
      end if;
   end Write_R_Pointer;

begin

   Writing : declare
      File        : Stream_IO.File_Type;
      File_Stream : Stream_IO.Stream_Access;
   begin
      Stream_IO.Create (File, Stream_IO.Out_File, "Demo_Output");
      --  Get access to the stream representing the file.
      File_Stream := Stream_IO.Stream (File);

      Put_Line ("Writing record to file: (10.0, 20.0)");
      R'Write (File_Stream, R'(10.0, 20.0)); --# Why is OK while data
mismached
                                             --# with paramter at line
15
      Put_Line ("Writing integer to file: 2005");
      Integer'Write (File_Stream, 2005);

      --  We use the 'Output stream attribute to write both the value
of this
      --  unconstrained type as well as the constraint (in this case,
the array
      --  bounds).
      Put_Line ("Writing string to file: ""Hello World!""");
      String'Output (File_Stream, "Hello World!");

      Put_Line ("Writing access value designating record (1.0, -1.0)
to file");
      R_Pointer'Write (File_Stream, new R'(1.0, -1.0));

      Stream_IO.Close (File);
   end Writing;

end Stream_IO_Demo_Cutdown;




^ permalink raw reply	[relevance 3%]

* Re: Reading Float Data from a binary file into ada
  @ 2007-01-30 19:31  2% ` Niklas Holsti
  0 siblings, 0 replies; 200+ results
From: Niklas Holsti @ 2007-01-30 19:31 UTC (permalink / raw)


frikk wrote:
> Hello everyone! I am having a problem that I would love some help 
> with.
> 
> Essentially I was given a Visual Basic program that dumps a binary 
> configuration file with all of the variables in a set.  The variables 
> are each 32 bit floats, with the first 16 bits being the integer part 
> and the second 16 bits being a representation of the fraction (I'm not 
> sure if this is stanard - but its just how VB dumps the data). The 
> binary dump is basically a copy of the way VB stores the data in 
> memory.  I need to be able to use this data in ada.  There is a C 
> counterpart to this that makes use of a 'union' to grab the data 1 
> byte (8 bits) at a time, put them into a char array of size 4, then 
> use a 32 bit float to reference the data.  Is there somehow I can do 
> this in ada as well?

If that approach works in C, the same approach should work in Ada, as 
follows:

- Read the file with Ada.Sequential_IO (instantiated for
   Interfaces.Unsigned_8) or with Ada.Streams.Stream_IO.
   If you haven't used Streams before, Sequential_IO may
   be easier to start with.

- Use the functions Shift_Left or Shift_Right together with
   the "or" operator (all from Interfaces) to assemble 4 octets
   (Unsigned_8 values) into one 32-bit value of type
   Interfaces.Unsigned_32. You may have to experiment to
   get the octets in the right order.

- Then use Unchecked_Conversion to go from Unsigned_32 to Float.

The portability of this approach is the same as for the C code: it 
depends on the byte order in the VB file, the order in which you 
concatenate the 4 octets into a 32-bit value, and the representation of 
Float values. But if it works in C, it should work in Ada, assuming that 
the Ada Float type has the same representation as the C float type, 
which is likely.

Hope this helps...

-- 
Niklas Holsti
Tidorum Ltd
niklas holsti tidorum fi
       .      @       .



^ permalink raw reply	[relevance 2%]

* Re: A smaller self contained test case. Was: Compiler Bug or what I'm doing wrong?
  @ 2006-06-24 19:58  2%           ` Dmitry A. Kazakov
  0 siblings, 0 replies; 200+ results
From: Dmitry A. Kazakov @ 2006-06-24 19:58 UTC (permalink / raw)


On 24 Jun 2006 15:53:32 +0200, M E Leypold wrote:

> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> writes:
> 
>> BTW, I wouldn't use discriminants with defaults, 
> 
> I'm perhaps misuing dicriminants anyway in that application. But they
> need to have defaults, since the disriminated records are fields in
> another record. Like
> 
>   type All_We_Know ( Internal_Data_Available : Boolean := True ) is record 
>     case Internal_Data_Available is
>          when True  =>  Secret_Data : ... ;
>          ...
>   end record;
> 
>   type ... is record 
>     Things_Known : All_We_Konw;
>     ...
>   end record;
>  
> (Ok, stupid example, but you get ist: Data not to be given to an
>  external data processing application can be supressed by the
>  discriminant).

All_We_Know looks much like a handle. Then I'd try to make it more OO, if
you aren't allergic to it. What about tagged types? (:-))

>> and in any case, would use
>> Input for them. 
> 
> I tried to do that, but that didn't fix the problem. I also wouldn't
> expect that: According to Barnes Input most probably uses Read.

Or a part of it. Anyway, try this:

with Ada.Text_IO;
with Ada.Streams.Stream_IO;  use Ada.Streams.Stream_IO;
with Ada.Strings.Unbounded;  use Ada.Strings.Unbounded;

procedure Bug3 is

  type Customer_Description (Is_Company : Boolean := True) is record
     case Is_Company Is
        when True =>
           Foo          : Integer := 0;       -- remove these and the
           Bar          : Integer := 0;       -- SIGSEGV goes away
           Company_Name : Unbounded_String ;
        when False =>
           Persons_Name : Unbounded_String;
        when others  =>  null;
     end case;
  end record;

  procedure Set_Zugang (D : in out Customer_Description; Z : Boolean) is
  begin
     if Z /= D.Is_Company then
        case Z is
           when True =>
              declare
                 New_D : Customer_Description (True);
              begin
                 D := New_D;
              end;
           when False  =>
              declare
                 New_D : Customer_Description (False);
              begin
                 D := New_D;
              end;
        end case;
     end if;
  end;

  procedure Write_Record is
     F : File_Type;
     S : Stream_Access;
     R : Customer_Description;
  begin
     Create (F, Name => "tmp-bug3");
     S := Stream (F);
     Set_Zugang (R, False);                   -- remove this and the
SIGSEGV goes away

     for I in 1 .. 400 loop
        Customer_Description'Output (S,R);     -- [1a]
     end loop;
     Close (F);
  end;

  procedure Get_Record is
     F : File_Type;
     S : Stream_Access;
  begin
     Open (F, Mode => In_File, Name => "tmp-bug3" );
     S := Stream (F);
     for I in 1 .. 400 loop
        declare
           R : Customer_Description renames
                  Customer_Description'Input (S);
        begin
           Ada.Text_IO.Put_Line ("Read" & Integer'Image (I));
        end;
     end loop;
     Close (F);
  end;

begin
  Write_Record;
  Get_Record;
end;

It should work with GNAT 3.15p / Windows.

>> 1. You have the discriminant stored anyway (that was the choice about
>> having the defaults), so you cannot use one stored value of the
>> discriminant for all 400 fields, even if they had it same.
> 
> Oops. That I don't understand.

If the discriminant had no default, then Write would not store it. So if
all 400 elements had the same value of the discriminant, you could first
store its value manually (Boolean'Write) and then use 'Write for each
element. When reading you'd read the discriminant value once and then use
Read on a variable constrained to that value:

type Foo (C : Boolean) is ...;

Boolean'Write (S, False);
for I in ... loop
   Foo'Write (S, Get_R (I)); -- I know that all C's are same
end loop;

declare
   C : Boolean;
begin
   Boolean'Read (S, C);
   declare
      R : Foo (C);
   begin
      for I in ... loop
         Foo'Real (S, R); -- I know that all C's are same
      end loop;

>> 2. Read means that you have one extra initialize / finalize pair. Input
>> does not:
> 
> I don't care. Input is slow anyway and doesn't happen so often :-).

So it is safe to use it, at least to work the bug around.

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



^ permalink raw reply	[relevance 2%]

* And a Workaround: Was: A smaller test case / Compiler Bug
  2006-06-23  9:55  2% ` A smaller self contained test case. Was: " M E Leypold
@ 2006-06-23 11:04  2%   ` M E Leypold
    1 sibling, 0 replies; 200+ results
From: M E Leypold @ 2006-06-23 11:04 UTC (permalink / raw)




Dear All,

Here is a workaround for the problem with reading/writing variant
records with finalizers which I reported before.

One should override the read/write attributes of the record in
question. The substituted procedures should 

  - write the discriminant first, then the appropriate variant part.

  - read the discriminant value, explicitly set the discriminant field
    in the buffer variable and then read the appropriate variant part.

"Fixed" test case has been attached.

Presently my idea about the source of the bug is, that the compiler
generates wrong code for reading records with discriminants.

Before it sets the discriminant field in the variable, it doesn't run
appropriate finalizers and initializers on possibly changed variant
parts, but just sets the discriminant field and the invokes the read
procedure for the appropriate variant part. Of course at that time the
bit patterns in record representation are not appropriate for the
discriminant (the representation is invalid) but mostly that doesn't
matter since the invalid representation is overwritten anyway. It does
matter though in the case that the variant part visible after changing
the discriminant value contains fields with controlled data types:
Then finalizers are run on invalid variable content. In my case that
triggered a problem in the underlying libc malloc().

The problem should only happen if there are variant parts where a
variant part has fields with finalizers _AND_ the representation
doesn't overlap with that of the other variant parts (in my test case
the problem goes away if the fields with finalizers are just 2
Unbounded_Strings, one at the beginning of every variant part, which
could be explained by the finalizer running as a finalizer of the
wrong variant part but still being a finalizer of Unbounded_String and
thus correctly finalizing the Unbounded_String in the now hidden
variant part.)

Depending on the finalizers all that leads to erronous memory
deallocation or that some finalization action is dropped (I've not
verfied this, but I predict that will probably happen).

The bug should in example result in memory leaks if the variant part
incoreectly hidden during reading contains finalizers concerned with
freeing memory which then are not run.

All that is conjecture at the moment but well in agreement with the
evidence so far.


Regards -- Markus


----

    with Ada.Streams.Stream_IO; use  Ada.Streams.Stream_IO;
    with Ada.Strings.Unbounded; use Ada.Strings.Unbounded;

    procedure Demo.Bug3 is

       type Customer_Description( Is_Company : Boolean := True ) is record

          case Is_Company Is

             when  True   =>

                Foo                 : Integer := 0;       -- remove these and the
                Bar                 : Integer := 0;       -- SIGSEGV goes away
                Company_Name        : Unbounded_String ;

             when  False  =>

                Persons_Name        : Unbounded_String;

             when   others  =>  null;
          end case;
       end record;

       procedure Write_Customer_Description
         ( S : access Ada.Streams.Root_Stream_Type'Class;
           R : in Customer_Description
         );

       procedure Read_Customer_Description
         ( S : access Ada.Streams.Root_Stream_Type'Class;
           R : out Customer_Description
         );


       for Customer_Description'Write use Write_Customer_Description;
       for Customer_Description'Read  use Read_Customer_Description;


       procedure Set_Zugang ( D :  in out Customer_Description ; Z : Boolean ) is begin

          if Z /= D.Is_Company then

             case Z is

                when True      =>
                   declare New_D : Customer_Description(True);
                   begin
                      D := New_D ;
                   end;

                when False  =>
                   declare New_D : Customer_Description(False);
                   begin   D := New_D ; end;

             end case;
          end if;
       end;


       procedure Write_Customer_Description
         ( S : access Ada.Streams.Root_Stream_Type'Class;
           R : in Customer_Description
         )
       is begin
          Boolean'Write(S,R.Is_Company);
          case R.Is_Company is

             when True =>
                Integer'Write( S, R.Foo );
                Integer'Write( S, R.Bar );
                Unbounded_String'Write( S, R.Company_Name );

             when False =>
                Unbounded_String'Write( S, R.Persons_Name );
          end case;
       end;


       procedure Read_Customer_Description
         ( S : access Ada.Streams.Root_Stream_Type'Class;
           R : out Customer_Description
         )
       is
          B : Boolean;
       begin
          Boolean'Read(S,B);
          Set_Zugang( R, B);

          case R.Is_Company is

             when True =>
                Integer'Read( S, R.Foo );
                Integer'Read( S, R.Bar );
                Unbounded_String'Read( S, R.Company_Name );

             when False =>
                Unbounded_String'Read( S, R.Persons_Name );
          end case;
       end;


       procedure Write_Record
       is
         F : File_Type;
         S : Stream_Access;
         R : Customer_Description;
       begin
          Create( F , Name => "tmp-bug3" );
          S := Stream(F);
          Set_Zugang(R, False);                   -- remove this and the SIGSEGV goes away

          for I in 1 .. 400 loop
             Customer_Description'Write(S,R);     -- [1a]
          end loop;

          Close(F);
       end;


       procedure Get_Record
       is
          F : File_Type;
          S : Stream_Access;
       begin

          Open( F , Mode => In_File, Name => "tmp-bug3" );
          S := Stream(F);

          for I in 1 .. 400 loop
             declare R : Customer_Description;
             begin
                Customer_Description'Read(S,R);        -- [1b]
             end;
          end loop;

          Close( F );
       end;

       R : Customer_Description;

    begin
       Write_Record;
       Get_Record;
    end;



^ permalink raw reply	[relevance 2%]

* A smaller self contained test case. Was: Compiler Bug or what I'm doing wrong?
  2006-06-20 16:56  1% Compiler Bug or what I'm doing wrong? M E Leypold
@ 2006-06-23  9:55  2% ` M E Leypold
  2006-06-23 11:04  2%   ` And a Workaround: Was: A smaller test case / Compiler Bug M E Leypold
    0 siblings, 2 replies; 200+ results
From: M E Leypold @ 2006-06-23  9:55 UTC (permalink / raw)




Dear All,

I'm attaching a smaller (and now self contained test case!) for the
SIGSEGV whil reading/writing varaint records which I wrote about
earlier.

Some data:

 1. Gnat 3.15p on Debian Sarge.
 2. Running the attached program wil result in a SIGSEGV in a finalizer.

I'm also attaching a short backtrace.

Regards -- Markus


---


     with Ada.Streams.Stream_IO; use  Ada.Streams.Stream_IO;
     with Ada.Strings.Unbounded; use Ada.Strings.Unbounded;

     procedure Demo.Bug3 is

        type Customer_Description( Is_Company : Boolean := True ) is record

           case Is_Company Is

              when  True   =>

                 Foo                 : Integer := 0;       -- remove these and the
                 Bar                 : Integer := 0;       -- SIGSEGV goes away
                 Company_Name        : Unbounded_String ;

              when  False  =>

                 Persons_Name        : Unbounded_String;

              when   others  =>  null;
           end case;
        end record;


        procedure Set_Zugang ( D :  in out Customer_Description ; Z : Boolean ) is begin

           if Z /= D.Is_Company then

              case Z is

                 when True      =>
                    declare New_D : Customer_Description(True);
                    begin
                       D := New_D ;
                    end;

                 when False  =>
                    declare New_D : Customer_Description(False);
                    begin   D := New_D ; end;

              end case;
           end if;
        end;


        procedure Write_Record
        is
          F : File_Type;
          S : Stream_Access;
          R : Customer_Description;
        begin
           Create( F , Name => "tmp-bug3" );
           S := Stream(F);
           Set_Zugang(R, False);                   -- remove this and the SIGSEGV goes away

           for I in 1 .. 400 loop
              Customer_Description'Write(S,R);     -- [1a]
           end loop;

           Close(F);
        end;


        procedure Get_Record
        is
           F : File_Type;
           S : Stream_Access;
        begin

           Open( F , Mode => In_File, Name => "tmp-bug3" );
           S := Stream(F);

           for I in 1 .. 400 loop
              declare R : Customer_Description;
              begin
                 Customer_Description'Read(S,R);        -- [1b]
              end;
           end loop;

           Close( F );
        end;

        R : Customer_Description;

     begin
        Write_Record;
        Get_Record;
     end;


---


Program received signal SIGSEGV, Segmentation fault.
0x408d1d41 in system__finalization_implementation__finalize_list ()
   from /usr/lib/libgnat-3.15p.so.1
#0  0x408d1d41 in system__finalization_implementation__finalize_list ()
   from /usr/lib/libgnat-3.15p.so.1
#1  0x408d1bdc in system__finalization_implementation__finalize ()
   from /usr/lib/libgnat-3.15p.so.1
#2  0x408d1d47 in system__finalization_implementation__finalize_list ()
   from /usr/lib/libgnat-3.15p.so.1
#3  0x0804cef9 in demo__bug3__get_record__B_4___clean.21 ()
#4  0x0804dec7 in demo.bug3.get_record () at demo-bug3.adb:77
#5  0x0804e203 in demo.bug3 () at demo-bug3.adb:88
#6  0x0804b4ad in main (argc=1, argv=(system.address) 0xbffff8a4,
    envp=(system.address) 0xbffff8ac) at b~demo-bug3.adb:180
#7  0x40930e36 in __libc_start_main () from /lib/libc.so.6



^ permalink raw reply	[relevance 2%]

* Compiler Bug or what I'm doing wrong?
@ 2006-06-20 16:56  1% M E Leypold
  2006-06-23  9:55  2% ` A smaller self contained test case. Was: " M E Leypold
  0 siblings, 1 reply; 200+ results
From: M E Leypold @ 2006-06-20 16:56 UTC (permalink / raw)




Hi all,

the following happens with GNAT 3.15p on Debian. My impression is,
that finalization during reading with the compiler generated
'Read-Attribute is not handled right in variant records, but I might
be wrong. Let me first expose the problem and my sample code.

I have the following Program (explanations below):


    with Sf.Cases;
    use  Sf.Cases;

    with Sf.Fieldtypes;
    use  Sf.Fieldtypes;

    with Ada.Streams.Stream_IO;
    use  Ada.Streams.Stream_IO;


    procedure Demo.Bug3 is

       procedure Write_Record
       is
         R : Fall_Datensatz;

         F : File_Type;
         S : Stream_Access;
       begin
          Create( F , Name => "tmp-bug3" );
          S := Stream(F);
          Set_Zugang(R, SelbstMelderIn);          -- [**]
          -- Fall_Datensatz'Output(S,R); -- [2a]
          Fall_Datensatz'Write(S,R);     -- [1a]
          Close(F);
       end;

       Function Get_Record return Fall_Datensatz
       is
          R: Fall_Datensatz;
          F : File_Type;
          S : Stream_Access;
       begin
          Open( F , Mode => In_File, Name => "tmp-bug3" );
          S := Stream(F);

          -- R := Fall_Datensatz'Input(S); -- [2b]
          Fall_Datensatz'Read(S,R);        -- [1b]
          Close( F );
          return R;
       end;

       R : Fall_Datensatz;

    begin
       Write_Record;
       R := Get_Record;
    end;


It instantiated a record with default initialization, changes a
discriminant in a which controls a variant part in the record (at [**]
Set_Zugang will be explained later), and then stores the record in a
file. When rereading the file (Get_Record), I get the following
exception:


   "raised PROGRAM_ERROR : demo-bug3.adb:38 finalize raised exception"

Running it under debugger control I get 

   (gdb) exec-file demo-bug3
   (gdb) run
   Starting program: /home/mel/cvswork/statfix/src2/demo-bug3

   Program received signal SIGSEGV, Segmentation fault.
   0x4098d354 in mallopt () from /lib/libc.so.6
   (gdb)

   (gdb) bt 5
   #0  0x4098d354 in mallopt () from /lib/libc.so.6
   #1  0x4098c15f in free () from /lib/libc.so.6
   #2  0x408f4e84 in __gnat_free () from /usr/lib/libgnat-3.15p.so.1
   #3  0x4082ac79 in ada__strings__unbounded__finalize__2 ()
      from /usr/lib/libgnat-3.15p.so.1
   #4  0x080c9fe5 in <demo__bug3__get_record___read654___read1116___read1147> (
       s=0x80e2e00, v=@0xbfffc39c, <sF>=0) at demo-bug3.adb:38
   (More stack frames follow...)
   (gdb)

which makes me suspect that a finalizer is run on non-appropriate data
(i.e. on the wrong part of a variant). I'll attach more stack traces
below, but first let me explain the data structure Fall_Datensatz
(which is defined in SF.Cases). I'm showing only the parts that are
actually touched by the program:


   type PA_Kontakt_Ergebnis ( Erfolg : Di_State := Keine_Angabe ) is record

      case Erfolg is
         when Ja     => Kontakt_Ergebnis : Auswahl_Kontakt_Ergebnis := Keine_Angabe;         
         when others => null;
      end case;
   end record;


   type PA_Kontakt_Verlauf
     ( Kontakt_Methode : Auswahl_Kontakt_Methode := Keine_Angabe )
   is record
      case Kontakt_Methode is
         when Keine_Angabe => null;
         when Keinen       => null;
         when Others       => Ergebnis : PA_Kontakt_Ergebnis;
      end case;
   end record;


   type Zugangs_Daten( KlientIn_Zugang : Auswahl_KlientIn_Zugang := Keine_Angabe ) is record

      case KlientIn_Zugang is

         when  Proaktiver_Kontakt  =>

            Kontakt_Vermittlung : Angabe_Kontakt_Vermittlung ;
            PA_Kontakt          : PA_Kontakt_Verlauf         ;

         when      SelbstmelderIn  =>

            KlientIn_Aufmerksamkeit : Angabe_Klientin_Aufmerksamkeit;

         when              others  =>  null;
      end case;
   end record;




   type Fall_Datensatz
     ( KJB_Verf�gbar : Boolean := True ; Notizen_Verf�gbar : Boolean := True )
   is record

      Aktenzeichen  : Fall_Aktenzeichen;
      Tat           : Fall_Merkmale     (Notizen_Verf�gbar);

      Opfer         : Personen_Merkmale (Notizen_Verf�gbar);
      T�ter         : Personen_Merkmale (Notizen_Verf�gbar);

      Zugang        : Zugangs_Daten;
      Polizei       : Angaben_Polizei_Einsatz;

      Beratung      : Beratungsverlauf  (Notizen_Verf�gbar);

      Kinder        : Kinder_Daten; -- (KJB_Verf�gbar, Notizen_Verf�gbar);

      case KJB_Verf�gbar is
         when  True   => null; -- KJB : ...
         when  False  => null;
      end case;
   end record;


The Unbounded Strings are hidden in Angabe_Kontakt_Vermittlung and
Angabe_Klientin_Aufmerksamkeit which are actually Types defined via a
generic package as an enumeration type with an optional comment (only
to be given in some cases):


   type Data is record
      Choice  : Choice_Type      := Choice_Type'First;
      Comment : Unbounded_String := Null_Unbounded_String;
   end record;


(I'll give the complete interface below, but this post becomes pretty
longish, so I'll restrict myself to what I consider the relevant parts).

The procedure Set_Zugang modifies the diosriminant of Zugangs_Daten in
the following way:


   procedure Set_Zugang ( D :  in out Zugangs_Daten ; Z : Auswahl_KlientIn_Zugang )
   is begin

      if Z /= D.KlientIn_Zugang then

         case Z is

            when Selbstmelderin      =>
               declare New_D : Zugangs_Daten(Selbstmelderin);
               begin
                  D := New_D ;
               end;

            when Proaktiver_Kontakt  =>
               declare New_D : Zugangs_Daten(Proaktiver_Kontakt);
               begin   D := New_D ; end;

            when Keine_Angabe        => D := (KlientIn_Zugang => Keine_Angabe ) ;
         end case;
      end if;
   end;


   procedure Set_Zugang ( DS :  in out Fall_Datensatz ; Z : Auswahl_KlientIn_Zugang) is begin

      Set_Zugang( DS.Zugang, Z );
   end;

(The idea is to have the initialisation defaults if and only if the
discrimant is changed).

If  (in gdb) I step up some stackframes and print the record R in
Get_Record I get the following


  (...)  zugang => (klientin_zugang => selbstmelderin,
         klientin_aufmerksamkeit => ( choice => keine_angabe, comment
         => (prev => 0x0, next => 0x0, reference => Cannot access
         memory at address 0x7a9f08

This is also what led me to the impression that first the discriminant
is overwritten and the the finalizer(s) for the new variant part
("when SelbstMelderIn") are run (on random bit patterns) instead of
the finalizers for the default variant part ("when Keine_Angabe
..."). 

(Actually I'd have expected in the case of discriminant records that
the whole thingy works like this: Run all finalizers in variant parts
if any, only then read the discriminant, run the initializers in the
new variant parts, then read the rest of the record).

After having a look into Barnes "Programming in Ada 95" again, I
thought, that perhaps I should use 'Input and 'Output instead of 'Read
an 'Write. This fixed the problem in the case above (options [2a] and
[2b]), but unfortunately failed to fix the the problem in the larger
program from which these fragments come.

Of course the bug is a Heisenbug so small changes in Fall_Datensatz or
the order of code execuation in the larger program make it disappear
which made it difficult in the first place to construct a relatively
small example w/o GUI which succeeds in reproducing the bug. 

Therefore I think (but again I'm not sure) that the fact that the bug
goes away with 'Input and Output instead of 'Read/'Write is just part
of it's elusive character not evidence of a fix. Also, since records
with default discriminants are definite I think 'Read and 'Write
should be OK for IO. Am I not right?

I've googled a bit, but didn't find anything on that, eehm,
"effect". But maybe I didn't use the right keywords. 

Is this a known bug with GNAT 3.15p or am I doing anything wrong?

Your help/input (also suggestions for workaround or confirmation that
this indeed a GNAT bug) would be greatly appreciated.

(Ludovico: I'll file an entry into Debian bug tracking soon. Just
looking for confirmation here first).

Regards -- Markus



ATTACHEMENTS: Backtraces and more code
--------------------------------------

  Sf.Single-Choices (Unit interface from which the types Angabe_* are instantiated) 
  ------------------
  
     with Ada.Strings.Unbounded;
     use  Ada.Strings.Unbounded;

     generic

        type Choice_Type   is (<>);
        type Choice_List   is array (Integer range <>) of Choice_Type;

        Allow_Comment_List : Choice_List;

     package Sf.Single_Choice is

        type Data is private;

        procedure Set( D : in out Data ; C : Choice_Type );
        function  Get( D : Data ) return Choice_Type;
        function  ID ( D : Data ) return Integer;

        function  Get_Comment( D : Data ) return String;
        procedure Set_Comment( D : in out Data; S : String );

        procedure Set_From_Integer( D : in out Data ; I : Integer );

        procedure Set( D : in out Data ; I : Integer ) renames Set_From_Integer;

        procedure Reset ( D : in out Data );

     private

        type Flags is array (Choice_Type) of Boolean;

        function Get_Comment_Allowed_Vector return Flags;

        Comment_Allowed : constant Flags := Get_Comment_Allowed_Vector;

        type Data is record
           Choice  : Choice_Type      := Choice_Type'First;
           Comment : Unbounded_String := Null_Unbounded_String;
        end record;
     end;



  complete backtrace
  ------------------

  #0  0x4098d354 in mallopt () from /lib/libc.so.6
  #1  0x4098c15f in free () from /lib/libc.so.6
  #2  0x408f4e84 in __gnat_free () from /usr/lib/libgnat-3.15p.so.1
  #3  0x4082ac79 in ada__strings__unbounded__finalize__2 ()
     from /usr/lib/libgnat-3.15p.so.1
  #4  0x080c9fe5 in <demo__bug3__get_record___read654___read1116___read1147> (
      s=0x80e2e00, v=@0xbfffc39c, <sF>=0) at demo-bug3.adb:38
  #5  0x080ca136 in <demo__bug3__get_record___read654___read1116> (s=0x80e2e00,
      v=@0xbfffc384, <sF>=0, <vF>=false) at demo-bug3.adb:38
  #6  0x080d5997 in <demo__bug3__get_record___read654> (s=0x80e2e00, v=@0xbfffc108,
      <sF>=0, <vF>=false) at demo-bug3.adb:38
  #7  0x080d869f in demo.bug3.get_record () at demo-bug3.adb:38
  #8  0x080dd625 in demo.bug3 () at demo-bug3.adb:48
  #9  0x080640dd in main (argc=1, argv=(system.address) 0xbffff8a4,
      envp=(system.address) 0xbffff8ac) at b~demo-bug3.adb:244
  #10 0x40930e36 in __libc_start_main () from /lib/libc.so.6


  more information
  ----------------

  I've generated a core and also can reproduce the SIGSEGV in this
  configuration 100% of the time. Don't hesitate to ask for more
  debugger output or more code.





^ permalink raw reply	[relevance 1%]

* Re: Q: Index value in case of Ada.Streams.Stream_IO.End_Error
  2006-04-24 16:05  2%     ` Jean-Pierre Rosen
@ 2006-04-24 17:44  2%       ` Gautier
  0 siblings, 0 replies; 200+ results
From: Gautier @ 2006-04-24 17:44 UTC (permalink / raw)


Jean-Pierre Rosen:

> If you use 'Read, and there is not enough bytes left in the file, then 
> your file is corrupted. You will get End_Error.
> Now, if you want to analyze what happened, here is what you can do:
> 1) before calling 'Read, get the current index (function Index)
> 2) Do a T'Read
> 3) If you get End_Error, do a Set_Index to return where you were, and 
> use the Read procedure to get the corresponding array of bytes.
> Then it's up to you...

Fine, it's what I'm doing currently (cf the lines of code in my 1st post).
But since the buffer in question happens to be a byte array,
I'll switch to the Read procedure and just define the buffer as a
Stream_Element_Array.
Thanks
_______________________________________________________________
Gautier         -- http://www.mysunrise.ch/users/gdm/index.htm
Ada programming -- http://www.mysunrise.ch/users/gdm/gsoft.htm



^ permalink raw reply	[relevance 2%]

* Re: Q: Index value in case of Ada.Streams.Stream_IO.End_Error
  2006-04-24 14:33  5%   ` Gautier
@ 2006-04-24 16:05  2%     ` Jean-Pierre Rosen
  2006-04-24 17:44  2%       ` Gautier
  0 siblings, 1 reply; 200+ results
From: Jean-Pierre Rosen @ 2006-04-24 16:05 UTC (permalink / raw)


Gautier a �crit :
> Jean-Pierre Rosen:
> 
>>> Is there a RM-documented way to know the Index of a 
>>> Ada.Streams.Stream_IO.File_Type
>>> when it knocks the end of a file at reading it ?
> 
>> out parameter Last in function Read...
>>
>> This gives you the number of bytes actually read.
> 
> You mean the _procedure_ Read, from Stream_IO ?
> 
>   procedure Read (File : in File_Type;
>                   Item : out Stream_Element_Array;
>                   Last : out Stream_Element_Offset);
> 
> Nice, but for my buffer I need to use the Read _attribute_ (13.13.2).
> 
If you use 'Read, and there is not enough bytes left in the file, then 
your file is corrupted. You will get End_Error.
Now, if you want to analyze what happened, here is what you can do:
1) before calling 'Read, get the current index (function Index)
2) Do a T'Read
3) If you get End_Error, do a Set_Index to return where you were, and 
use the Read procedure to get the corresponding array of bytes.
Then it's up to you...
-- 
---------------------------------------------------------
            J-P. Rosen (rosen@adalog.fr)
Visit Adalog's web site at http://www.adalog.fr



^ permalink raw reply	[relevance 2%]

* Re: Q: Index value in case of Ada.Streams.Stream_IO.End_Error
  2006-04-24  8:11  2% ` Jean-Pierre Rosen
@ 2006-04-24 14:33  5%   ` Gautier
  2006-04-24 16:05  2%     ` Jean-Pierre Rosen
  0 siblings, 1 reply; 200+ results
From: Gautier @ 2006-04-24 14:33 UTC (permalink / raw)


Jean-Pierre Rosen:

>> Is there a RM-documented way to know the Index of a 
>> Ada.Streams.Stream_IO.File_Type
>> when it knocks the end of a file at reading it ?

> out parameter Last in function Read...
> 
> This gives you the number of bytes actually read.

You mean the _procedure_ Read, from Stream_IO ?

   procedure Read (File : in File_Type;
                   Item : out Stream_Element_Array;
                   Last : out Stream_Element_Offset);

Nice, but for my buffer I need to use the Read _attribute_ (13.13.2).

procedure S'Read( Stream : access Ada.Streams.Root_Stream_Type'Class;
                   Item : out T)

No "Last" there... If I try:

         IO_buf'Read( Ada.Streams.Stream_IO.Stream(infile), inbuf, last );

a compiler says as expected:
unz_io.adb:55:67: unexpected argument for "Read" attribute

Hence my question.
Mmmh, unless I redefine my buffer as a Stream_Element_Array.
Are you assuming that ?
_______________________________________________________________
Gautier         -- http://www.mysunrise.ch/users/gdm/index.htm
Ada programming -- http://www.mysunrise.ch/users/gdm/gsoft.htm

NB: For a direct answer, e-mail address on the Web site!



^ permalink raw reply	[relevance 5%]

* Re: Q: Index value in case of Ada.Streams.Stream_IO.End_Error
  2006-04-22  1:33  5% Q: Index value in case of Ada.Streams.Stream_IO.End_Error Gautier
@ 2006-04-24  8:11  2% ` Jean-Pierre Rosen
  2006-04-24 14:33  5%   ` Gautier
  0 siblings, 1 reply; 200+ results
From: Jean-Pierre Rosen @ 2006-04-24  8:11 UTC (permalink / raw)


Gautier a �crit :
> Hello!
> 
> Is there a RM-documented way to know the Index of a 
> Ada.Streams.Stream_IO.File_Type
> when it knocks the end of a file at reading it ?
out parameter Last in function Read...

This gives you the number of bytes actually read.
-- 
---------------------------------------------------------
            J-P. Rosen (rosen@adalog.fr)
Visit Adalog's web site at http://www.adalog.fr



^ permalink raw reply	[relevance 2%]

* Q: Index value in case of Ada.Streams.Stream_IO.End_Error
@ 2006-04-22  1:33  5% Gautier
  2006-04-24  8:11  2% ` Jean-Pierre Rosen
  0 siblings, 1 reply; 200+ results
From: Gautier @ 2006-04-22  1:33 UTC (permalink / raw)


Hello!

Is there a RM-documented way to know the Index of a Ada.Streams.Stream_IO.File_Type
when it knocks the end of a file at reading it ?
I did not see a mention of what value the Index should have in that situation in
the RM 95, so for the moment I prefer to reread a partial buffer byte per byte
in order to know what has been effectively read. But maybe - hopefully - there
is a better way.

   procedure Read_buffer is

     procedure Byte_per_byte is
     begin
       for i in inbuf'Range loop
         Byte'Read( Ada.Streams.Stream_IO.Stream(infile), inbuf(i) );
         readpos:= readpos + 1;
       end loop;
     exception
       when Ada.Streams.Stream_IO.End_Error => null;
       -- nothing, we just reached EOF again
     end Byte_per_byte;

     start: Ada.Streams.Stream_IO.Positive_Count:=
              Ada.Streams.Stream_IO.Index(infile);
   begin
     readpos:= 0;
     begin
       IO_buf'Read( Ada.Streams.Stream_IO.Stream(infile), inbuf );
       readpos:= inbuf'Length;
     exception
       when Ada.Streams.Stream_IO.End_Error =>
         -- End reached, re-read in order to know the last position
         Ada.Streams.Stream_IO.Set_Index(infile, start);
         Read_buffer.Byte_per_byte;
     end;
   end Read_buffer;

Thanks in advance!
_______________________________________________________________
Gautier         -- http://www.mysunrise.ch/users/gdm/index.htm
Ada programming -- http://www.mysunrise.ch/users/gdm/gsoft.htm

NB: For a direct answer, e-mail address on the Web site!



^ permalink raw reply	[relevance 5%]

* Re: Sending Variable Length Messages with GNAT.Sockets
  @ 2005-05-09 18:49  2%         ` Adrien Plisson
  0 siblings, 0 replies; 200+ results
From: Adrien Plisson @ 2005-05-09 18:49 UTC (permalink / raw)


markp wrote:
> Thanks John.
> 
> I still have a fundamental problem. I am working on legacy code in
> which data is defined in records (or arrays of records) which are sent
> in variable lengths. We use address, byte count to send the exact
> number of bytes. Using Streams, it seems they type has to be of
> Stream_element_Array. The only way I can see to send/receive these
> "variable" messages is to first read our message header which contains
> the number of bytes in the message. Then, create a Stream_Element_Array
> of the exact size for the next read. Then, do an unchecked conversion
> or a copy bytes routine to get the data into my data type for
> processing. Does this sound correct?

this sounds bof bof... a bit complicated...

since you seem still struggling on this, here is some help, based on 
wild guesses i made given your previous posts:

with Ada.Text_IO,
      Ada.Streams,
      Ada.Streams.Stream_IO;
procedure Main is
     -- let's assume you have this kind of records
     type Data_Record is record
         Some : Integer;
         Dummy : String (1..8);
         Fields : Float;
     end record;

     -- according to the description you gave in a previous post,
     -- your message type is implemented (simplified) this way
     type Data_Record_Array is array (1..512) of Data_Record;
     type Message is record
         -- the message header (very simplified)
         -- holds the number of actual records in the data
         Number_Of_Records : Natural;
         -- the message data
         Data : Data_Record_Array;
     end record;

     -- declaration of the custom stream attribute procedures
     procedure Message_Read( Stream : access 
Ada.Streams.Root_Stream_Type'Class; Msg : out Message );
     for Message'Read use Message_Read;
     procedure Message_Write( Stream : access 
Ada.Streams.Root_Stream_Type'Class; Msg : in Message );
     for Message'Write use Message_Write;

     -- implementation of Message'Read
     procedure Message_Read( Stream : access 
Ada.Streams.Root_Stream_Type'Class; Msg : out Message ) is
         Size : Natural;
     begin
         -- first read the header
         -- WARNING: on the network, the size is in bytes,
         -- not in number of records
         Natural'Read( Stream, Size );
         Msg.Number_Of_Records := Size / (Data_Record'Size / 
Ada.Streams.Stream_Element'Size);

         -- then read the data
         for I in Msg.Data'First..Msg.Data'First + Msg.Number_Of_Records 
- 1 loop
             Data_Record'Read( Stream, Msg.Data(I) );
         end loop;
     end Message_Read;

     -- implementation of Message'Write
     procedure Message_Write( Stream : access 
Ada.Streams.Root_Stream_Type'Class; Msg : in Message ) is
     begin
         -- first write the header
         -- WARNING: on the network, the size is in bytes,
         -- not in number of records
         Natural'Write( Stream, Msg.Number_Of_Records * Data_Record'Size 
/ Ada.Streams.Stream_Element'Size );

         -- then write the data
         for I in Msg.Data'First..Msg.Data'First + Msg.Number_Of_Records 
- 1 loop
             Data_Record'Write( Stream, Msg.Data(I) );
         end loop;
     end Message_Write;


     -- this is for to simplify test writing
     use Ada.Streams.Stream_IO;

begin
     -- since socket streams and file streams are identical (really, all 
streams work the same)
     -- we will use files for testing

     -- first write some stuffs to a stream
     declare
         F : File_Type;
         S : Stream_Access;
         M : Message;

     begin
         -- create a new file
         Create( F, Out_File, "test.out" );
         -- get the stream corresponding to the file
         S := Stream( F );

         -- create 5 messages
         for I in 1..5 loop
             -- fill each message with dummy data
             M.Number_Of_Records := I * 2;
             for J in 1..M.Number_Of_Records loop
                 M.Data(J) := Data_Record'(Some => J, Dummy => 
"20050509", Fields => 42.0 / Float( I ) + Float( J ));
             end loop;

             -- write the data to the stream
             Message'Write( S, M );
         end loop;

         -- close the file
         Close( F );
     end;

     -- here you can look at "test.out" and see what it contains.

     -- now read some stuffs from the stream
     declare
         F : File_Type;
         S : Stream_Access;
         M : Message;

     begin
         -- open the file
         Open( F, In_File, "test.out" );
         -- get the stream corresponding to the file
         S := Stream( F );

         -- read all messages on the stream
         loop
             Message'Read( S, M );

             -- display the content of the messages
             Ada.Text_IO.Put_Line( "Message found : " & Natural'Image( 
M.Number_Of_Records ) & " records =>" );
             for I in M.Data'First..M.Data'First + M.Number_Of_Records - 
1 loop
                 Ada.Text_IO.Put_Line( "    " & Integer'Image( 
M.Data(I).Some ) & " " & M.Data(I).Dummy & " " & Float'Image( 
M.Data(I).Fields ) );
             end loop;
         end loop;
     exception
         when End_Error =>
             -- when there are no more messages in the stream file,
             -- close it
             Close( F );
     end;
end Main;

-- 
rien




^ permalink raw reply	[relevance 2%]

* Re: [Shootout] Spellcheck.adb
  @ 2005-04-26 19:36  1% ` David Sauvage
  0 siblings, 0 replies; 200+ results
From: David Sauvage @ 2005-04-26 19:36 UTC (permalink / raw)


Hi,

happy to read your post, also because i'm the folk who proposed the 
spellcheck ada implementation :-), i don't undestand yet the shootout 
spellcheck error as it works nicely on my system, does it failed on 
yours too ? may be you could describe the errors here if so ? thanks

albert.bachmann@gmx.de wrote:
> Now what I'd like to ask you is how I can speed up my Ada solution? 
You can find interesting discussion on the spellcheck implementation & 
speed issue in the thread named "Ada Bench" of comp.lang.ada
you could use :
- Ada.Streams.Stream_IO.Read instead of Ada.Text_IO.Get_Line
- the shootout spellcheck C++ hash function as hash function

albert.bachmann@gmx.de wrote:
> 
> real    0m0.742s
> user    0m0.720s
> sys     0m0.009s
> 
Is it for N=1 ? could you describe your system configuration & the 
command line used to launch the program ?

Well done, i was about 5 min on my first implementation ;-)
here is the shootout spellcheck implementation (for N=1) duration, you 
can take a look on my system configuration on the Ada Bench thread :
real    0m0.126s
user    0m0.078s
sys     0m0.013s

To compare (just because we are talking about benchmark and how to speed 
up our programs) here is your posted implementation on my system (i add 
the line with Ada.Strings.Fixed; as "strings.fixed.delete" was not 
handle by my compiler without it)
real    0m1.432s
user    0m1.361s
sys     0m0.014s

Your next version should be far far better ;-)

Hope it could help ;-)
David



^ permalink raw reply	[relevance 1%]

* Re: Ada bench
  2005-04-20  0:49  0%             ` Matthew Heaney
@ 2005-04-20 21:24  2%               ` David Sauvage
  0 siblings, 0 replies; 200+ results
From: David Sauvage @ 2005-04-20 21:24 UTC (permalink / raw)


Hi,

"Matthew Heaney" <mhea...@on2.com> wrote
> This is good data.  Can you make a version that uses the (indefinite)
> hashed set too, and post those results?
>
> Also, can you post a data set with the new hash function (see below)?


- The same Ada.Streams.Stream_IO.Read method is used in all the
following cases
- Please do not take the following real time values as _serious_, as
just a few runs have been done to make a rapid average. I'm also afraid
about the influence of my system load average on the time command used
to get the real cpu time.
- I did not figure out how to use Reserve_Capacity in
Indefinite_Hashed_Maps & Indefinite_Hashed_Sets.
- Using GNAT 3.15p-12 on GNU Debian/Linux, for other system
characteristics please have a look on my previous post.
- http://psycose.apinc.org/ada_shootout/ also contain the
spellcheck_ada-ai302_hashed_set & spellcheck_ada-ai302_hashed_map
tarball.

 AI302.Containers.Indefinite_Hashed_Maps + C++ spellcheck hash function
: 240
 AI302.Containers.Indefinite_Hashed_Maps + AI302.Strings.Hash function
: 257
 AI302.Containers.Indefinite_Hashed_Sets
: 370


--
David




^ permalink raw reply	[relevance 2%]

* Re: Ada bench
  2005-04-19 23:22  2%           ` David Sauvage
  2005-04-20  0:49  0%             ` Matthew Heaney
@ 2005-04-20  9:41  0%             ` Pascal Obry
  1 sibling, 0 replies; 200+ results
From: Pascal Obry @ 2005-04-20  9:41 UTC (permalink / raw)



"David Sauvage" <pariakaman@gmail.com> writes:

> GNAT.Spitbol.Table + Ada.Streams.Stream_IO    (*1)              : 145
> GNAT.Spitbol.Table + Ada.Text_IO                                : 175
> AI302.Containers.Indefinite_Hashed_Maps + Ada.Streams.Stream_IO : 278
> AI302.Containers.Indefinite_Hashed_Maps + Ada.Text_IO           : 310

There is probably a not so good hash routin implementation in the AI302
containers and you end up with many collisions.

You should try the one from GNAT s-htable.adb:

<<
   function Hash (Key : String) return Header_Num is

      type Uns is mod 2 ** 32;

      function Rotate_Left (Value : Uns; Amount : Natural) return Uns;
      pragma Import (Intrinsic, Rotate_Left);

      Hash_Value : Uns;

   begin
      Hash_Value := 0;
      for J in Key'Range loop
         Hash_Value := Rotate_Left (Hash_Value, 3) + Character'Pos (Key (J));
      end loop;

      return Header_Num'First +
               Header_Num'Base (Hash_Value mod Header_Num'Range_Length);
   end Hash;
>>

Pascal.

-- 

--|------------------------------------------------------
--| Pascal Obry                           Team-Ada Member
--| 45, rue Gabriel Peri - 78114 Magny Les Hameaux FRANCE
--|------------------------------------------------------
--|              http://www.obry.net
--| "The best way to travel is by means of imagination"
--|
--| gpg --keyserver wwwkeys.pgp.net --recv-key C1082595



^ permalink raw reply	[relevance 0%]

* Re: Ada bench
  2005-04-19 23:22  2%           ` David Sauvage
@ 2005-04-20  0:49  0%             ` Matthew Heaney
  2005-04-20 21:24  2%               ` David Sauvage
  2005-04-20  9:41  0%             ` Pascal Obry
  1 sibling, 1 reply; 200+ results
From: Matthew Heaney @ 2005-04-20  0:49 UTC (permalink / raw)


"David Sauvage" <pariakaman@gmail.com> writes:

> - for the GNAT.Spitbol.Table method, i just instantiate the generic
> with 40_000 as discriminant (same value as the C spellcheck
> implementation)

I would also call Reserve_Capacity with a value of 40_000, in both the
hashed map and hashed set versions.


> - for the AI302.Containers.Indefinite_Hashed_Maps method i used the
> default AI302.Strings.Hash as hash function
> - When using the Ada.Streams.Stream_IO method, i used a 4_096 buffer.
> 
> GNAT.Spitbol.Table + Ada.Streams.Stream_IO    (*1)              : 145
> GNAT.Spitbol.Table + Ada.Text_IO                                : 175
> AI302.Containers.Indefinite_Hashed_Maps + Ada.Streams.Stream_IO : 278
> AI302.Containers.Indefinite_Hashed_Maps + Ada.Text_IO           : 310

This is good data.  Can you make a version that uses the (indefinite)
hashed set too, and post those results?

Also, can you post a data set with the new hash function (see below)?


> "Matthew Heaney" <mhea...@on2.com> wrote
> > Have you tried using the C++ hash function with an Ada program that
> > uses Ada.Containers.Hashed_Maps?
> 
> nop, excellent i will try this soon.

Here's the hash function:

function Hash_Word (S : String) return Hash_Type is
   H : Hash_Type := 0;
begin
   for I in S'Range loop
      H := 5 * H + Character'Pos (S (I));
   end loop;
   return H;
end Hash_Word;


-Matt



^ permalink raw reply	[relevance 0%]

* Re: Ada bench
  2005-04-19 16:43  0%         ` Matthew Heaney
@ 2005-04-19 23:22  2%           ` David Sauvage
  2005-04-20  0:49  0%             ` Matthew Heaney
  2005-04-20  9:41  0%             ` Pascal Obry
  0 siblings, 2 replies; 200+ results
From: David Sauvage @ 2005-04-19 23:22 UTC (permalink / raw)


Hi,
thanks for your advised comments,

"Matthew Heaney" <mhea...@on2.com> wrote
> How do you know from where the improvement came -- the change in
> data structure or the change in read mechanism?

please not i run the program just a few times to get an average value.
(System config : GNU/Debian Sid kernel 2.6.10, AMD 1.2 Ghz)
- Values are in millisecond, N=1
- for the GNAT.Spitbol.Table method, i just instantiate the generic
with 40_000 as discriminant (same value as the C spellcheck
implementation)
- for the AI302.Containers.Indefinite_Hashed_Maps method i used the
default AI302.Strings.Hash as hash function
- When using the Ada.Streams.Stream_IO method, i used a 4_096 buffer.

GNAT.Spitbol.Table + Ada.Streams.Stream_IO    (*1)              : 145
GNAT.Spitbol.Table + Ada.Text_IO                                : 175
AI302.Containers.Indefinite_Hashed_Maps + Ada.Streams.Stream_IO : 278
AI302.Containers.Indefinite_Hashed_Maps + Ada.Text_IO           : 310

"Matthew Heaney" <mhea...@on2.com> wrote
> Have you tried using the C++ hash function with an Ada program that
> uses Ada.Containers.Hashed_Maps?

nop, excellent i will try this soon.

(*1) this implementaton can be also find here
http://psycose.apinc.org/ada_shootout/

--
David




^ permalink raw reply	[relevance 2%]

* Re: Ada bench
  2005-04-18 19:14  2%       ` David Sauvage
@ 2005-04-19 16:43  0%         ` Matthew Heaney
  2005-04-19 23:22  2%           ` David Sauvage
  0 siblings, 1 reply; 200+ results
From: Matthew Heaney @ 2005-04-19 16:43 UTC (permalink / raw)



David Sauvage wrote:
>
> I've proposed a new spellcheck version without using the AI-302
> Containers, i've used GNAT.Spitbol.Table. The app is twice faster. I
> also used Ada.Streams.Stream_IO.Read.

How do you know from where the improvement came -- the change in data
structure or the change in read mechanism?

Also, what hash function have you been using?  I just compared
Ada.Strings.Hash to the hash function used in the C++ example, and the
C++ hash function does much better on the words in spellcheck-dict.txt.

Have you tried using the C++ hash function with an Ada program that
uses Ada.Containers.Hashed_Maps?

Note that strictly speaking, you don't need to use the hashed map,
since the shootout is comparing "hash tables."  In the standard
library, there are two kinds of hash tables, hashed maps and hashed
sets.  In the shootout spellcheck example, you only need a membership
test, so a hashed set will do just as well.  (Probably better, in
fact.)

-Matt




^ permalink raw reply	[relevance 0%]

* Re: Ada bench
  @ 2005-04-18 19:14  2%       ` David Sauvage
  2005-04-19 16:43  0%         ` Matthew Heaney
  0 siblings, 1 reply; 200+ results
From: David Sauvage @ 2005-04-18 19:14 UTC (permalink / raw)


Hi,

I've proposed a new spellcheck version without using the AI-302
Containers, i've used GNAT.Spitbol.Table. The app is twice faster. I
also used Ada.Streams.Stream_IO.Read

--
David




^ permalink raw reply	[relevance 2%]

* Re: Ada bench : count words
  2005-03-23 15:09  2%               ` Marius Amado Alves
@ 2005-03-30 16:08  0%                 ` Andre
  0 siblings, 0 replies; 200+ results
From: Andre @ 2005-03-30 16:08 UTC (permalink / raw)



Marius Amado Alves wrote:
>> I'll review this tomorrow on the bus to work (I think your program is 
>> separating words at buffer end, and it should not).
> 
> 
> Done. Tmoran, sorry, my first sight was wrong, your algorithm is mostly 
> fine. Minor reservations:
> - special statute given to CR; personally I think all characters 
> (control or not) should count to total
> - reliance on Stream_Element representing one character; portable across 
> all range of environments?
> 
> My own program rewritten with Text_Streams attains the same speed as 
> yours. The fact that it is structured doesn't hit performance 
> significantly. Pragma Inline improves a little bit. Real times (ms) on 
> my iBook, for input file repeated 2500 times, all compiled with only -O3:
> C ........................ 600
> Yours, or mine inlined ... 700
> Mine not inlined ......... 750
> 
> So we should submit yours, or mine inlined. It will put Ada right after 
> the Cs w.r.t. speed. W.r.t. executable file size Ada is much bigger. On 
> my iBook:
> C .......  15k
> Mine .... 423k
> Yours ... 459k
> 
> W.r.t. source code size all are similar. Number of significant 
> semicolons (Ada), or semicolons + {} blocks + #includes + #defines (C):
> C .............. 27
> Yours .......... 33
> Mine inlined ... 52
> 
> My program follows for reference. It accepts the code for EOL as an 
> argument. Default = 10 (LF).
> 
> -- The Great Computer Language Shootout
> -- http://shootout.alioth.debian.org/
> -- 
> -- contributed by Guys De Cla
> 
> with Ada.Characters.Handling;
> with Ada.Characters.Latin_1;
> with Ada.Command_Line;
> with Ada.Streams;
> with Ada.Streams.Stream_IO;
> with Ada.Strings.Fixed;
> with Ada.Text_IO;
> with Ada.Text_IO.Text_Streams;
> 
> procedure Count_Words_Portable is
> 
>    use Ada.Characters.Handling;
>    use Ada.Characters.Latin_1;
>    use Ada.Command_Line;
>    use Ada.Streams;
>    use Ada.Streams.Stream_IO;
>    use Ada.Text_IO;
>    use Ada.Text_IO.Text_Streams;
> 
>    Buffer : Stream_Element_Array (1 .. 4096);
>    Input_Stream : Ada.Text_IO.Text_Streams.Stream_Access
>      := Ada.Text_IO.Text_Streams.Stream (Current_Input);
>    EOL_Character_Pos : Stream_Element := Character'Pos (LF);
>    Lines : Natural := 0;
>    Words : Natural := 0;
>    Total : Natural := 0;
>    In_Word : Boolean := False;
>    N : Stream_Element_Offset;
>    Is_Separator : array (Stream_Element) of Boolean :=
>      (0 .. 32 | 127 .. 159 => True, others => False);
> 
>    procedure Begin_Word is
>    begin
>       Words := Words + 1;
>       In_Word := True;
>    end;
> 
>    procedure End_Word is
>    begin
>       In_Word := False;
>    end;
> 
>    procedure End_Line is
>    begin
>       Lines := Lines + 1;
>       End_Word;
>    end;
> 
>    procedure Count_Words (S : in Stream_Element_Array) is
>    begin
>       Total := Total + S'Length;
>       for I in S'Range loop
>          if S (I) = EOL_Character_Pos then
>             End_Line;
>          else
>             if Is_Separator (S (I)) then
>                if In_Word then End_Word; end if;
>             else
>                if not In_Word then Begin_Word; end if;
>             end if;
>          end if;
>       end loop;
>    end;
> 
>    pragma Inline (Begin_Word, End_Word, End_Line, Count_Words);
> 
> begin
>    begin
>       EOL_Character_Pos := Stream_Element'Value (Argument (1));
>    exception
>       when Constraint_Error => null;
>    end;
>    Ada.Text_IO.Put_Line ("EOL =>" & Stream_Element'Image 
> (EOL_Character_Pos));
> 
>    loop
>       Read (Root_Stream_Type'Class (Input_Stream.all), Buffer, N);
>       Count_Words (Buffer (1 .. N));
>       exit when N < Buffer'Length;
>    end loop;
> 
>    Ada.Text_IO.Put_Line
>      (Natural'Image (Lines) &
>       Natural'Image (Words) &
>       Natural'Image (Total));
> end;
> 

I checked with the Shootout side. The Ada program sent in was rated with 
Error. So, maybe you can check why and correct it.

Andr�


^ permalink raw reply	[relevance 0%]

* Re: Gnat 3.15p & Windows & Hyperthreading Q
  2005-03-26 18:36  2% ` tmoran
@ 2005-03-28 13:16  0%   ` Marin David Condic
  0 siblings, 0 replies; 200+ results
From: Marin David Condic @ 2005-03-28 13:16 UTC (permalink / raw)


On a quick scan, I don't see anything obvious. Let me take a look at it 
and I'll see if I spot anything that might be problematic.

MDC

tmoran@acm.org wrote:
> 
>     The original program was posted under "Ada bench : count words",
> as was the dual-Celeron timing.  The hyperthreading timing was a personal
> communication.  It's possible the person was mistaken in thinking they
> had hyperthreading turned on, with processor affinities set correctly.
> I'm inquiring further.
> 
>   So here's the benchmark.  It reads a text file from Standard Input,
> preferably at least a megabyte to get a decent timing read, and prints
> line, word, and character counts to Standard Output.  The number of
> CPU-heavy tasks is the number of elements of
>   Counter : array(1 .. 2) of Counters;
> Probably increasing the buffer size, by lessening task interactions,
> would speed it up and improve the multi-tasking benefit.
> 
> with Ada.Calendar,
>      Ada.Streams,
>      Ada.Streams.Stream_IO,
>      Ada.Text_IO,
>      Ada.Text_IO.Text_Streams;
> procedure Cwt is
>   use Ada.Streams;
>   use type Ada.Calendar.Time;
> 
>   T0  : Ada.Calendar.Time := Ada.Calendar.Clock;  -- start timing
>   T1  : Ada.Calendar.Time;
> 
>   subtype Buffer_Type is Stream_Element_Array(1 .. 4096);
> 
>   LF      : constant Stream_Element := Character'pos(Ascii.LF);
>   Is_Whitespace : constant array(Stream_Element) of Boolean
>     := (Character'pos(Ascii.LF) | Character'pos(Ascii.HT)
>         | Character'pos(' ') => True, others => False);
> 
>   -- "Counters" tasks run independently, asking Data_Source for buffer loads
>   -- and tallying word and line counts.  When done, they wait for their
>   -- (partial) counts to be harvested, then terminate.
> 
>   task type Counters is
>     entry Harvest(Line_Count, Word_Count : out Natural);
>   end Counters;
> 
>   -- Data_Source is the IO task, supplying data as requested to Counters.
>   -- Note that Data_Source counts the whitespace->non-white transitions
>   -- at the ends of buffers.  Counters' partial counts are added to that.
>   -- Data_Source also counts the Total number of characters.
> 
>   task Data_Source is
>     entry Get(Buffer : out Buffer_Type;
>               Last : out Stream_Element_Offset);
>   end Data_Source;
> 
>   task body Counters is
>     Buffer : Buffer_Type;
>     Last : Stream_Element_Offset;
>     Lines, Words, Total : Natural := 0;
>     In_Whitespace : Boolean;
>   begin
>     loop
>       Data_Source.Get(Buffer, Last);
>       exit when Last = 0;
>       In_Whitespace := Is_Whitespace(Buffer(1));
>       for I in 1 .. Last loop
>         if Is_Whitespace(Buffer(I)) then
>           if Buffer(I) = LF then
>             Lines := Lines + 1;
>           end if;
>           In_Whitespace := True;
>         elsif In_Whitespace then
>           In_Whitespace := False;
>           Words := Words + 1;
>         end if;
>       end loop;
>       exit when Last < Buffer'last;
>     end loop;
>     accept Harvest(Line_Count, Word_Count : out Natural) do
>       Line_Count := Lines;
>       Word_Count := Words;
>     end;
>   end Counters;
> 
>   Lines, Words, Total : Natural := 0;
> 
>   task body Data_Source is
>     Stream  : Ada.Text_IO.Text_Streams.Stream_Access;
>     At_End : Boolean := False;
>     In_Whitespace : Boolean := True; -- we must count at edges of buffer loads
>   begin
>     Stream := Ada.Text_IO.Text_Streams.Stream(Ada.Text_IO.Current_Input);
>     loop
>       select
>         accept Get(Buffer : out Buffer_Type;
>                    Last : out Stream_Element_Offset) do
>           if At_End then Last := 0;
>           else
>             Ada.Streams.Read(Ada.Streams.Root_Stream_Type'Class(Stream.all),
>                              Buffer, Last);
>             Total := Total+Integer(Last);
>             if Last > 0 then
>               if In_Whitespace and not Is_Whitespace(Buffer(1)) then
>                 Words := Words+1;
>               end if;
>               In_Whitespace := Is_Whitespace(Buffer(Last));
>             end if;
>             if Last < Buffer'last then At_End := True;end if;
>           end if;
>         end;
>       or terminate;
>       end select;
>     end loop;
>   end Data_Source;
> 
>   A_Line_Count, A_Word_Count : Natural := 0;
> 
>   Counter : array(1 .. 2) of Counters;
> 
> begin
> 
>   for i in Counter'range loop
>     Counter(i).Harvest(A_Line_Count, A_Word_Count);
>     Lines := Lines+A_Line_Count;
>     Words := Words+A_Word_Count;
>   end loop;
> 
>   T1 := Ada.Calendar.Clock;
> 
>   Ada.Text_IO.Put_Line(Natural'Image(Lines)
>                        & Natural'Image(Words)
>                        & Natural'Image(Total));
>   Ada.Text_IO.Put_Line("took" & Duration'Image(T1 - T0));
> end Cwt;

-- 
======================================================================
Marin David Condic
I work for: http://www.belcan.com/
My project is: http://www.jsf.mil/NSFrames.htm

Send Replies To: m   o   d   c @ a   m   o   g
                    c   n   i       c   .   r

     "'Shut up,' he explained."

         --  Ring Lardner
======================================================================



^ permalink raw reply	[relevance 0%]

* Re: Gnat 3.15p & Windows & Hyperthreading Q
  @ 2005-03-26 18:36  2% ` tmoran
  2005-03-28 13:16  0%   ` Marin David Condic
  0 siblings, 1 reply; 200+ results
From: tmoran @ 2005-03-26 18:36 UTC (permalink / raw)


> >   I'm told that a multitask program compiled with Gnat 3.15p and run
> > under Windows XP Pro on a hyperthreaded machine, runs in the same total
> > time as the same program using a single task.  OTOH, when compiled with
> > GNAT 5.02a1 and run on a dual-processor 400 MHz Celeron running Mandrake
> > Linux 8.2, it runs about 50% faster with two rather than one tasks.
>
> That seems strange. In the first case, is it a SINGLE processor machine?
> Or is it the same dual processor 400mhz Celeron in both cases?
> Also, is this just anecdotal or is there an actual benchmark program
> that could be looked at?
    The original program was posted under "Ada bench : count words",
as was the dual-Celeron timing.  The hyperthreading timing was a personal
communication.  It's possible the person was mistaken in thinking they
had hyperthreading turned on, with processor affinities set correctly.
I'm inquiring further.

  So here's the benchmark.  It reads a text file from Standard Input,
preferably at least a megabyte to get a decent timing read, and prints
line, word, and character counts to Standard Output.  The number of
CPU-heavy tasks is the number of elements of
  Counter : array(1 .. 2) of Counters;
Probably increasing the buffer size, by lessening task interactions,
would speed it up and improve the multi-tasking benefit.

with Ada.Calendar,
     Ada.Streams,
     Ada.Streams.Stream_IO,
     Ada.Text_IO,
     Ada.Text_IO.Text_Streams;
procedure Cwt is
  use Ada.Streams;
  use type Ada.Calendar.Time;

  T0  : Ada.Calendar.Time := Ada.Calendar.Clock;  -- start timing
  T1  : Ada.Calendar.Time;

  subtype Buffer_Type is Stream_Element_Array(1 .. 4096);

  LF      : constant Stream_Element := Character'pos(Ascii.LF);
  Is_Whitespace : constant array(Stream_Element) of Boolean
    := (Character'pos(Ascii.LF) | Character'pos(Ascii.HT)
        | Character'pos(' ') => True, others => False);

  -- "Counters" tasks run independently, asking Data_Source for buffer loads
  -- and tallying word and line counts.  When done, they wait for their
  -- (partial) counts to be harvested, then terminate.

  task type Counters is
    entry Harvest(Line_Count, Word_Count : out Natural);
  end Counters;

  -- Data_Source is the IO task, supplying data as requested to Counters.
  -- Note that Data_Source counts the whitespace->non-white transitions
  -- at the ends of buffers.  Counters' partial counts are added to that.
  -- Data_Source also counts the Total number of characters.

  task Data_Source is
    entry Get(Buffer : out Buffer_Type;
              Last : out Stream_Element_Offset);
  end Data_Source;

  task body Counters is
    Buffer : Buffer_Type;
    Last : Stream_Element_Offset;
    Lines, Words, Total : Natural := 0;
    In_Whitespace : Boolean;
  begin
    loop
      Data_Source.Get(Buffer, Last);
      exit when Last = 0;
      In_Whitespace := Is_Whitespace(Buffer(1));
      for I in 1 .. Last loop
        if Is_Whitespace(Buffer(I)) then
          if Buffer(I) = LF then
            Lines := Lines + 1;
          end if;
          In_Whitespace := True;
        elsif In_Whitespace then
          In_Whitespace := False;
          Words := Words + 1;
        end if;
      end loop;
      exit when Last < Buffer'last;
    end loop;
    accept Harvest(Line_Count, Word_Count : out Natural) do
      Line_Count := Lines;
      Word_Count := Words;
    end;
  end Counters;

  Lines, Words, Total : Natural := 0;

  task body Data_Source is
    Stream  : Ada.Text_IO.Text_Streams.Stream_Access;
    At_End : Boolean := False;
    In_Whitespace : Boolean := True; -- we must count at edges of buffer loads
  begin
    Stream := Ada.Text_IO.Text_Streams.Stream(Ada.Text_IO.Current_Input);
    loop
      select
        accept Get(Buffer : out Buffer_Type;
                   Last : out Stream_Element_Offset) do
          if At_End then Last := 0;
          else
            Ada.Streams.Read(Ada.Streams.Root_Stream_Type'Class(Stream.all),
                             Buffer, Last);
            Total := Total+Integer(Last);
            if Last > 0 then
              if In_Whitespace and not Is_Whitespace(Buffer(1)) then
                Words := Words+1;
              end if;
              In_Whitespace := Is_Whitespace(Buffer(Last));
            end if;
            if Last < Buffer'last then At_End := True;end if;
          end if;
        end;
      or terminate;
      end select;
    end loop;
  end Data_Source;

  A_Line_Count, A_Word_Count : Natural := 0;

  Counter : array(1 .. 2) of Counters;

begin

  for i in Counter'range loop
    Counter(i).Harvest(A_Line_Count, A_Word_Count);
    Lines := Lines+A_Line_Count;
    Words := Words+A_Word_Count;
  end loop;

  T1 := Ada.Calendar.Clock;

  Ada.Text_IO.Put_Line(Natural'Image(Lines)
                       & Natural'Image(Words)
                       & Natural'Image(Total));
  Ada.Text_IO.Put_Line("took" & Duration'Image(T1 - T0));
end Cwt;



^ permalink raw reply	[relevance 2%]

* Re: Ada bench : word frequency
  @ 2005-03-24  1:24  2%       ` Marius Amado Alves
  0 siblings, 0 replies; 200+ results
From: Marius Amado Alves @ 2005-03-24  1:24 UTC (permalink / raw)
  To: comp.lang.ada

Program fixed. Zero differences with the reference result.

It's two times slower than the GCC C benchmark :-(

(CPU times (user+sys) on my iBook for n=25 repetitions of the input 
file: C => 0.75, Ada => 1.45)

However that's already enough to put Ada on the 7th place, after OCaml 
and before Eiffel :-)

Program follows.

with Ada.Characters.Handling;
with Ada.Characters.Latin_1;
with Ada.Command_Line;
with Ada.Streams;
with Ada.Streams.Stream_IO;
with Ada.Strings.Fixed;
with Ada.Text_IO;
with Ada.Text_IO.Text_Streams;

procedure Word_Frequency is

    use Ada.Characters.Handling;
    use Ada.Characters.Latin_1;
    use Ada.Command_Line;
    use Ada.Streams;
    use Ada.Streams.Stream_IO;
    use Ada.Text_IO;
    use Ada.Text_IO.Text_Streams;

    Buffer : Stream_Element_Array (1 .. 4096);
    Input_Stream : Ada.Text_IO.Text_Streams.Stream_Access
      := Ada.Text_IO.Text_Streams.Stream (Current_Input);
    N : Stream_Element_Offset;
    Is_Separator : array (Stream_Element) of Boolean :=
      (Character'Pos ('A') .. Character'Pos ('Z') |
       Character'Pos ('a') .. Character'Pos ('z') => False,
       others => True);

    -- N-ary tree of word counts
    -- used to increment the counts in one pass of the input file
    -- branches on the letter
    -- carries the count
    -- very fast
    -- but very space consuming

    subtype Letter is Stream_Element range
      Character'Pos ('a') .. Character'Pos ('z');
    type Word is array (Positive range <>) of Letter;
    type Tree;
    type Tree_Ptr is access Tree;
    type Node is
       record
          Count : Natural := 0;
          Subtree : Tree_Ptr := null;
       end record;
    type Tree is array (Letter) of Node;

    procedure Inc (X : in out Integer) is begin X := X + 1; end;
    procedure Dec (X : in out Integer) is begin X := X - 1; end;

    procedure Inc_Word (Parent : Tree_Ptr; Descendents : Word) is
    begin
       if Descendents'Length > 0 then
          declare
             Child_Index : Positive := Descendents'First;
             Child : Letter renames Descendents (Child_Index);
          begin
             if Descendents'Length = 1 then
                Inc (Parent (Child).Count);
             else
                if Parent (Child).Subtree = null then
                   Parent (Child).Subtree := new Tree;
                end if;
                Inc_Word
                  (Parent (Child).Subtree,
                   Descendents (Child_Index + 1 .. Descendents'Last));
             end if;
          end;
       end if;
    end;

    -- Binary tree of word counts
    -- used for sorting the result by the count (frequency)
    -- branches on the word count
    -- carries the word form

    type Form_Ptr is access Word;
    type Binary_Tree;
    type Binary_Tree_Ptr is access Binary_Tree;
    type Binary_Tree is
       record
          Form : Form_Ptr;
          Count : Natural;
          Left, Right : Binary_Tree_Ptr;
       end record;

    procedure Add_Node (Parent : in out Binary_Tree_Ptr; Form : 
Form_Ptr; Count : Natural) is
    begin
       if Parent = null then
          Parent := new Binary_Tree;
          Parent.Form := Form;
          Parent.Count := Count;
       else
          if Count < Parent.Count then
             Add_Node (Parent.Left, Form, Count);
          else
             Add_Node (Parent.Right, Form, Count);
          end if;
       end if;
    end;

    -- end of binary tree primitives

    Root : Tree_Ptr := new Tree;
    Btree : Binary_Tree_Ptr := null;
    Current_Word : Word (1 .. 1000);
    Current_Word_Length : Natural range 0 .. Current_Word'Last := 0;
    In_Word : Boolean := False;

    procedure Append_To_Word (E : Letter) is
    begin
       Inc (Current_Word_Length);
       Current_Word (Current_Word_Length) := E;
       In_Word := True;
    end;

    procedure End_Word is
    begin
       if Current_Word_Length > 0 then
          Inc_Word (Root, Current_Word (1 .. Current_Word_Length));
       end if;
       Current_Word_Length := 0;
       In_Word := False;
    end;

    To_Lower : array (Stream_Element) of Letter;

    procedure Initialise_To_Lower_Map is
       D : Integer := Character'Pos ('a') - Character'Pos ('A');
    begin
       for I in Character'Pos ('a') .. Character'Pos ('z') loop
          To_Lower (Stream_Element (I)) := Letter (I);
          To_Lower (Stream_Element (I - D)) := Letter (I);
       end loop;
    end;

    procedure Process (S : Stream_Element_Array) is
    begin
       for I in S'Range loop
          if Is_Separator (S (I)) then
             if In_Word then End_Word; end if;
          else
             Append_To_Word (To_Lower (S (I)));
          end if;
       end loop;
    end;

    procedure Populate_Btree (Ntree : Tree_Ptr) is
    begin
       Inc (Current_Word_Length);
       for I in Letter'Range loop
          Current_Word (Current_Word_Length) := I;
          if Ntree (I).Count > 0 then
             Add_Node
                (Btree,
                 Form => new Word'(Current_Word (1 .. 
Current_Word_Length)),
                 Count => Ntree (I).Count);
          end if;
          if Ntree (I).Subtree /= null then
             Populate_Btree (Ntree (I).Subtree);
          end if;
       end loop;
       Dec (Current_Word_Length);
    end;

    procedure Populate_Btree is
    begin
       Current_Word_Length := 0;
       Populate_Btree (Root);
    end;

    function To_String (X : Form_Ptr) return String is
       S : String (X'Range);
    begin
       for I in X'Range loop
          S (I) := Character'Val (X (I));
       end loop;
       return S;
    end;

    subtype String7 is String (1 .. 7);

    function Img7 (X : Natural) return String7 is
       S : String := Natural'Image (X);
    begin
       return String' (1 .. 8 - S'Length => ' ') & S (2 .. S'Last);
    end;

    procedure Dump_Btree (X : Binary_Tree_Ptr := Btree) is
    begin
       if X /= null then
          Dump_Btree (X.Right);
          Ada.Text_IO.Put_Line
            (Img7 (X.Count) & " " & To_String (X.Form));
          Dump_Btree (X.Left);
       end if;
    end;

begin
    Initialise_To_Lower_Map;
    loop
       Read (Root_Stream_Type'Class (Input_Stream.all), Buffer, N);
       Process (Buffer (1 .. N));
       exit when N < Buffer'Length;
    end loop;
    if In_Word then End_Word; end if;
    Populate_Btree;
    Dump_Btree;
end;




^ permalink raw reply	[relevance 2%]

* Re: Ada bench : count words
  @ 2005-03-23 21:38  2% ` tmoran
  0 siblings, 0 replies; 200+ results
From: tmoran @ 2005-03-23 21:38 UTC (permalink / raw)


Here's a simple multitasking conversion.  I would appreciate it if someone
with a dual core or hyperthreaded CPU tried it out.  Probably increasing
the buffer size, by lessening task interactions, would speed it up.  With
multiple CPUs, the array
  Counter : array(1 .. 2) of Counters;
might be increased to more tasks, also.

with Ada.Calendar,
     Ada.Streams,
     Ada.Streams.Stream_IO,
     Ada.Text_IO,
     Ada.Text_IO.Text_Streams;
procedure Cwt is
  use Ada.Streams;
  use type Ada.Calendar.Time;

  T0  : Ada.Calendar.Time := Ada.Calendar.Clock;  -- start timing
  T1  : Ada.Calendar.Time;

  subtype Buffer_Type is Stream_Element_Array(1 .. 4096);

  LF      : constant Stream_Element := Character'pos(Ascii.LF);
  Is_Whitespace : constant array(Stream_Element) of Boolean
    := (Character'pos(Ascii.LF) | Character'pos(Ascii.HT)
        | Character'pos(' ') => True, others => False);

  -- "Counters" tasks run independently, asking Data_Source for buffer loads
  -- and tallying word and line counts.  When done, they wait for their
  -- (partial) counts to be harvested, then terminate.

  task type Counters is
    entry Harvest(Line_Count, Word_Count : out Natural);
  end Counters;

  -- Data_Source is the IO task, supplying data as requested to Counters.
  -- Note that Data_Source counts the whitespace->non-white transitions
  -- at the ends of buffers.  Counters' partial counts are added to that.
  -- Data_Source also counts the Total number of characters.

  task Data_Source is
    entry Get(Buffer : out Buffer_Type;
              Last : out Stream_Element_Offset);
  end Data_Source;

  task body Counters is
    Buffer : Buffer_Type;
    Last : Stream_Element_Offset;
    Lines, Words, Total : Natural := 0;
    In_Whitespace : Boolean;
  begin
    loop
      Data_Source.Get(Buffer, Last);
      exit when Last = 0;
      In_Whitespace := Is_Whitespace(Buffer(1));
      for I in 1 .. Last loop
        if Is_Whitespace(Buffer(I)) then
          if Buffer(I) = LF then
            Lines := Lines + 1;
          end if;
          In_Whitespace := True;
        elsif In_Whitespace then
          In_Whitespace := False;
          Words := Words + 1;
        end if;
      end loop;
      exit when Last < Buffer'last;
    end loop;
    accept Harvest(Line_Count, Word_Count : out Natural) do
      Line_Count := Lines;
      Word_Count := Words;
    end;
  end Counters;

  Lines, Words, Total : Natural := 0;

  task body Data_Source is
    Stream  : Ada.Text_IO.Text_Streams.Stream_Access;
    At_End : Boolean := False;
    In_Whitespace : Boolean := True; -- we must count at edges of buffer loads
  begin
    Stream := Ada.Text_IO.Text_Streams.Stream(Ada.Text_IO.Current_Input);
    loop
      select
        accept Get(Buffer : out Buffer_Type;
                   Last : out Stream_Element_Offset) do
          if At_End then Last := 0;
          else
            Ada.Streams.Read(Ada.Streams.Root_Stream_Type'Class(Stream.all),
                             Buffer, Last);
            Total := Total+Integer(Last);
            if Last > 0 then
              if In_Whitespace and not Is_Whitespace(Buffer(1)) then
                Words := Words+1;
              end if;
              In_Whitespace := Is_Whitespace(Buffer(Last));
            end if;
            if Last < Buffer'last then At_End := True;end if;
          end if;
        end;
      or terminate;
      end select;
    end loop;
  end Data_Source;

  A_Line_Count, A_Word_Count : Natural := 0;

  Counter : array(1 .. 2) of Counters;

begin

  for i in Counter'range loop
    Counter(i).Harvest(A_Line_Count, A_Word_Count);
    Lines := Lines+A_Line_Count;
    Words := Words+A_Word_Count;
  end loop;

  T1 := Ada.Calendar.Clock;

  Ada.Text_IO.Put_Line(Natural'Image(Lines)
                       & Natural'Image(Words)
                       & Natural'Image(Total));
  Ada.Text_IO.Put_Line("took" & Duration'Image(T1 - T0));
end Cwt;



^ permalink raw reply	[relevance 2%]

* Ada bench : word frequency
  @ 2005-03-23 20:39  2%   ` Marius Amado Alves
    0 siblings, 1 reply; 200+ results
From: Marius Amado Alves @ 2005-03-23 20:39 UTC (permalink / raw)
  To: comp.lang.ada

Here's a shot at the word frequency benchmark. By my calculations, it 
is as fast as the GCC C benchmark. I did not compare the output with 
the reference output. A line-by-line comparison requires a criterion 
for words with the same frequency, which AFAICT is not documented. 
Also, my current concept of word separator does not include punctuation 
marks. Again, I could not find a reference definition.

The program does not use any external data structures library. It 
includes its own specific structures, an n-ary tree keyed by word form, 
and a binary tree keyed by word frequency. It increments the counts in 
the n-ary tree, then traverses the n-ary tree to populate the binary 
tree (to order by count), then dumps the latter.

with Ada.Characters.Handling;
with Ada.Characters.Latin_1;
with Ada.Command_Line;
with Ada.Streams;
with Ada.Streams.Stream_IO;
with Ada.Strings.Fixed;
with Ada.Text_IO;
with Ada.Text_IO.Text_Streams;

procedure Word_Frequency is

    use Ada.Characters.Handling;
    use Ada.Characters.Latin_1;
    use Ada.Command_Line;
    use Ada.Streams;
    use Ada.Streams.Stream_IO;
    use Ada.Text_IO;
    use Ada.Text_IO.Text_Streams;

    Buffer : Stream_Element_Array (1 .. 4096);
    Input_Stream : Ada.Text_IO.Text_Streams.Stream_Access
      := Ada.Text_IO.Text_Streams.Stream (Current_Input);
    N : Stream_Element_Offset;
    Is_Separator : array (Stream_Element) of Boolean :=
      (0 .. 32 | 127 .. 159 => True, others => False);

    -- N-ary tree of word counts
    -- used to increment the counts in one pass of the input file
    -- branches on the letter
    -- carries the count
    -- very fast
    -- but very space consuming

    subtype Letter is Stream_Element range 0 .. 255;
    type Word is array (Positive range <>) of Letter;
    type Tree;
    type Tree_Ptr is access Tree;
    type Node is
       record
          Count : Natural := 0;
          Subtree : Tree_Ptr := null;
       end record;
    type Tree is array (Letter) of Node;

    procedure Inc (X : in out Integer) is begin X := X + 1; end;
    procedure Dec (X : in out Integer) is begin X := X - 1; end;

    procedure Inc_Word (Parent : Tree_Ptr; Descendents : Word) is
    begin
       if Descendents'Length > 0 then
          declare
             Child_Index : Positive := Descendents'First;
             Child : Letter renames Descendents (Child_Index);
          begin
             if Descendents'Length = 1 then
                Inc (Parent (Child).Count);
             else
                if Parent (Child).Subtree = null then
                   Parent (Child).Subtree := new Tree;
                end if;
                Inc_Word
                  (Parent (Child).Subtree,
                   Descendents (Child_Index + 1 .. Descendents'Last));
             end if;
          end;
       end if;
    end;

    -- Binary tree of word counts
    -- used for sorting the result by the count (frequency)
    -- branches on the word count
    -- carries the word form

    type Form_Ptr is access Word;
    type Binary_Tree;
    type Binary_Tree_Ptr is access Binary_Tree;
    type Binary_Tree is
       record
          Form : Form_Ptr;
          Count : Natural;
          Left, Right : Binary_Tree_Ptr;
       end record;

    procedure Add_Node (Parent : in out Binary_Tree_Ptr; Form : 
Form_Ptr; Count : Natural) is
    begin
       if Parent = null then
          Parent := new Binary_Tree;
          Parent.Form := Form;
          Parent.Count := Count;
       else
          if Count < Parent.Count then
             Add_Node (Parent.Left, Form, Count);
          else
             Add_Node (Parent.Right, Form, Count);
          end if;
       end if;
    end;

    -- end of binary tree primitives

    Root : Tree_Ptr := new Tree;
    Btree : Binary_Tree_Ptr := null;
    Current_Word : Word (1 .. 1000);
    Current_Word_Length : Natural range 0 .. Current_Word'Last := 0;
    In_Word : Boolean := False;

    procedure Append_To_Word (E : Stream_Element) is
    begin
       Inc (Current_Word_Length);
       Current_Word (Current_Word_Length) := E;
       In_Word := True;
    end;

    procedure End_Word is
    begin
       if Current_Word_Length > 0 then
          Inc_Word (Root, Current_Word (1 .. Current_Word_Length));
       end if;
       Current_Word_Length := 0;
       In_Word := False;
    end;

    procedure Process (S : Stream_Element_Array) is
    begin
       for I in S'Range loop
          if Is_Separator (S (I)) then
             if In_Word then End_Word; end if;
          else
             Append_To_Word (S (I));
          end if;
       end loop;
    end;

    procedure Populate_Btree (Ntree : Tree_Ptr) is
    begin
       Inc (Current_Word_Length);
       for I in Letter'Range loop
          Current_Word (Current_Word_Length) := I;
          if Ntree (I).Count > 0 then
             Add_Node
                (Btree,
                 Form => new Word'(Current_Word (1 .. 
Current_Word_Length)),
                 Count => Ntree (I).Count);
          end if;
          if Ntree (I).Subtree /= null then
             Populate_Btree (Ntree (I).Subtree);
          end if;
       end loop;
       Dec (Current_Word_Length);
    end;

    procedure Populate_Btree is
    begin
       Current_Word_Length := 0;
       Populate_Btree (Root);
    end;

    function To_String (X : Form_Ptr) return String is
       S : String (X'Range);
    begin
       for I in X'Range loop
          S (I) := Character'Val (X (I));
       end loop;
       return S;
    end;

    procedure Dump_Btree (X : Binary_Tree_Ptr := Btree) is
    begin
       if X /= null then
          Dump_Btree (X.Right);
          Ada.Text_IO.Put_Line
            (To_String (X.Form) &
             Natural'Image (X.Count));
          Dump_Btree (X.Left);
       end if;
    end;

begin
    loop
       Read (Root_Stream_Type'Class (Input_Stream.all), Buffer, N);
       Process (Buffer (1 .. N));
       exit when N < Buffer'Length;
    end loop;
    if In_Word then End_Word; end if;
    Populate_Btree;
    Dump_Btree;
end;




^ permalink raw reply	[relevance 2%]

* Re: Ada bench : count words
       [not found]                 ` <00b362390273e6c04844dd4ff1885ee0@netcabo.pt>
@ 2005-03-23 15:09  2%               ` Marius Amado Alves
  2005-03-30 16:08  0%                 ` Andre
  0 siblings, 1 reply; 200+ results
From: Marius Amado Alves @ 2005-03-23 15:09 UTC (permalink / raw)
  To: comp.lang.ada

> I'll review this tomorrow on the bus to work (I think your program is 
> separating words at buffer end, and it should not).

Done. Tmoran, sorry, my first sight was wrong, your algorithm is mostly 
fine. Minor reservations:
- special statute given to CR; personally I think all characters 
(control or not) should count to total
- reliance on Stream_Element representing one character; portable 
across all range of environments?

My own program rewritten with Text_Streams attains the same speed as 
yours. The fact that it is structured doesn't hit performance 
significantly. Pragma Inline improves a little bit. Real times (ms) on 
my iBook, for input file repeated 2500 times, all compiled with only 
-O3:
C ........................ 600
Yours, or mine inlined ... 700
Mine not inlined ......... 750

So we should submit yours, or mine inlined. It will put Ada right after 
the Cs w.r.t. speed. W.r.t. executable file size Ada is much bigger. On 
my iBook:
C .......  15k
Mine .... 423k
Yours ... 459k

W.r.t. source code size all are similar. Number of significant 
semicolons (Ada), or semicolons + {} blocks + #includes + #defines (C):
C .............. 27
Yours .......... 33
Mine inlined ... 52

My program follows for reference. It accepts the code for EOL as an 
argument. Default = 10 (LF).

-- The Great Computer Language Shootout
-- http://shootout.alioth.debian.org/
--
-- contributed by Guys De Cla

with Ada.Characters.Handling;
with Ada.Characters.Latin_1;
with Ada.Command_Line;
with Ada.Streams;
with Ada.Streams.Stream_IO;
with Ada.Strings.Fixed;
with Ada.Text_IO;
with Ada.Text_IO.Text_Streams;

procedure Count_Words_Portable is

    use Ada.Characters.Handling;
    use Ada.Characters.Latin_1;
    use Ada.Command_Line;
    use Ada.Streams;
    use Ada.Streams.Stream_IO;
    use Ada.Text_IO;
    use Ada.Text_IO.Text_Streams;

    Buffer : Stream_Element_Array (1 .. 4096);
    Input_Stream : Ada.Text_IO.Text_Streams.Stream_Access
      := Ada.Text_IO.Text_Streams.Stream (Current_Input);
    EOL_Character_Pos : Stream_Element := Character'Pos (LF);
    Lines : Natural := 0;
    Words : Natural := 0;
    Total : Natural := 0;
    In_Word : Boolean := False;
    N : Stream_Element_Offset;
    Is_Separator : array (Stream_Element) of Boolean :=
      (0 .. 32 | 127 .. 159 => True, others => False);

    procedure Begin_Word is
    begin
       Words := Words + 1;
       In_Word := True;
    end;

    procedure End_Word is
    begin
       In_Word := False;
    end;

    procedure End_Line is
    begin
       Lines := Lines + 1;
       End_Word;
    end;

    procedure Count_Words (S : in Stream_Element_Array) is
    begin
       Total := Total + S'Length;
       for I in S'Range loop
          if S (I) = EOL_Character_Pos then
             End_Line;
          else
             if Is_Separator (S (I)) then
                if In_Word then End_Word; end if;
             else
                if not In_Word then Begin_Word; end if;
             end if;
          end if;
       end loop;
    end;

    pragma Inline (Begin_Word, End_Word, End_Line, Count_Words);

begin
    begin
       EOL_Character_Pos := Stream_Element'Value (Argument (1));
    exception
       when Constraint_Error => null;
    end;
    Ada.Text_IO.Put_Line ("EOL =>" & Stream_Element'Image 
(EOL_Character_Pos));

    loop
       Read (Root_Stream_Type'Class (Input_Stream.all), Buffer, N);
       Count_Words (Buffer (1 .. N));
       exit when N < Buffer'Length;
    end loop;

    Ada.Text_IO.Put_Line
      (Natural'Image (Lines) &
       Natural'Image (Words) &
       Natural'Image (Total));
end;




^ permalink raw reply	[relevance 2%]

* Re: Ada bench : count words
  2005-03-22 19:49  2%           ` tmoran
  2005-03-22 21:51  0%             ` Dmitry A. Kazakov
@ 2005-03-22 22:33  0%             ` Marius Amado Alves
       [not found]                 ` <00b362390273e6c04844dd4ff1885ee0@netcabo.pt>
  2 siblings, 0 replies; 200+ results
From: Marius Amado Alves @ 2005-03-22 22:33 UTC (permalink / raw)
  To: comp.lang.ada

On 22 Mar 2005, at 19:49, tmoran@acm.org wrote:

>> - the speed is circa 1/3 of the GCC C version
>> ...
>> The complete program follows.
>
>   I missed the original post with the URL of the benchmark, but this
> appears on my machine to be about 5x as fast (gnatmake -gnato -O2):

Excelent.

> with Ada.Calendar,
>      Ada.Streams,
>      Ada.Streams.Stream_IO,
>      Ada.Text_IO,
>      Ada.Text_IO.Text_Streams;

I'm so stupid! I had forgotten about Text_Streams!
I'll review this tomorrow on the bus to work (I think your program is 
separating words at buffer end, and it should not).




^ permalink raw reply	[relevance 0%]

* Re: Ada bench : count words
  2005-03-22 19:49  2%           ` tmoran
@ 2005-03-22 21:51  0%             ` Dmitry A. Kazakov
  2005-03-22 22:33  0%             ` Marius Amado Alves
       [not found]                 ` <00b362390273e6c04844dd4ff1885ee0@netcabo.pt>
  2 siblings, 0 replies; 200+ results
From: Dmitry A. Kazakov @ 2005-03-22 21:51 UTC (permalink / raw)


On Tue, 22 Mar 2005 13:49:26 -0600, tmoran@acm.org wrote:

>> - the speed is circa 1/3 of the GCC C version
>> ...
>> The complete program follows.
> 
>   I missed the original post with the URL of the benchmark,

I saw two:

http://shootout.alioth.debian.org/great/benchmark.php?test=wc&lang=all&sort=fullcpu,

and

http://dada.perl.it/shootout/wc.html

> but this
> appears on my machine to be about 5x as fast (gnatmake -gnato -O2):
> 
> with Ada.Calendar,
>      Ada.Streams,
>      Ada.Streams.Stream_IO,
>      Ada.Text_IO,
>      Ada.Text_IO.Text_Streams;
> procedure Cw is
>   use Ada.Streams;
>   use type Ada.Calendar.Time;
>   Stream  : Ada.Text_IO.Text_Streams.Stream_Access;
>   Buffer  : Stream_Element_Array(1 .. 4096);
>   Last    : Stream_Element_Offset;
>   Lines, Words, Total : Natural := 0;
>   In_Word : Boolean := False;
>   LF      : constant Stream_Element := Character'pos(Ascii.LF);
>   CR      : constant Stream_Element := Character'pos(Ascii.CR);
>   EOF_Char: constant Stream_Element := 16#1A#;
>   Is_Separator: constant array (Stream_Element) of Boolean
>     := (0 .. 32 | 127 .. 159 => True, others => False);

It seems (from the description) that the separators are HT, SP, LF.
Everything else is a "letter".

>   T0, T1  : Ada.Calendar.Time;
> begin
> 
>   T0 := Ada.Calendar.Clock;

No, they count load time as the run-time to be run as:

for i in 1 2 3 4 5 6 7 8 9 10; do time command done

So better link all static! (:-))

>   Stream := Ada.Text_IO.Text_Streams.Stream(Ada.Text_IO.Current_Input);
>   Through_File:
>   loop
>     Ada.Streams.Read(Ada.Streams.Root_Stream_Type'Class(Stream.all),
>                      Buffer, Last);
>     for I in 1 .. Last loop
>       exit Through_File when Buffer(I) = EOF_Char;
>       Total := Total + 1;
>       if Is_Separator(Buffer(I)) then
>         In_Word := False;
>         if Buffer(I) = LF then -- LF counts toward Total and toward Lines
>           Lines := Lines + 1;
>         elsif Buffer(I) = CR then -- don't count CR as content or as a line
>           Total := Total-1;

Remove this, CR is a letter! (:-))

>         end if;
>       else
>         if not In_Word then
>           Words := Words + 1;
>           In_Word := True;
>         end if;
>       end if;
>     end loop;
>     exit Through_File when Last < Buffer'Last;
>   end loop Through_File;
> 
>   T1 := Ada.Calendar.Clock;
> 
>   Ada.Text_IO.Put_Line(Natural'Image(Lines)
>                        & Natural'Image(Words)
>                        & Natural'Image(Total));
>   Ada.Text_IO.Put_Line("took" & Duration'Image(T1 - T0));
> end Cw;

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



^ permalink raw reply	[relevance 0%]

* Re: Ada bench : count words
    @ 2005-03-22 19:49  2%           ` tmoran
  2005-03-22 21:51  0%             ` Dmitry A. Kazakov
                               ` (2 more replies)
  1 sibling, 3 replies; 200+ results
From: tmoran @ 2005-03-22 19:49 UTC (permalink / raw)


> - the speed is circa 1/3 of the GCC C version
> ...
> The complete program follows.

  I missed the original post with the URL of the benchmark, but this
appears on my machine to be about 5x as fast (gnatmake -gnato -O2):

with Ada.Calendar,
     Ada.Streams,
     Ada.Streams.Stream_IO,
     Ada.Text_IO,
     Ada.Text_IO.Text_Streams;
procedure Cw is
  use Ada.Streams;
  use type Ada.Calendar.Time;
  Stream  : Ada.Text_IO.Text_Streams.Stream_Access;
  Buffer  : Stream_Element_Array(1 .. 4096);
  Last    : Stream_Element_Offset;
  Lines, Words, Total : Natural := 0;
  In_Word : Boolean := False;
  LF      : constant Stream_Element := Character'pos(Ascii.LF);
  CR      : constant Stream_Element := Character'pos(Ascii.CR);
  EOF_Char: constant Stream_Element := 16#1A#;
  Is_Separator: constant array (Stream_Element) of Boolean
    := (0 .. 32 | 127 .. 159 => True, others => False);
  T0, T1  : Ada.Calendar.Time;
begin

  T0 := Ada.Calendar.Clock;

  Stream := Ada.Text_IO.Text_Streams.Stream(Ada.Text_IO.Current_Input);
  Through_File:
  loop
    Ada.Streams.Read(Ada.Streams.Root_Stream_Type'Class(Stream.all),
                     Buffer, Last);
    for I in 1 .. Last loop
      exit Through_File when Buffer(I) = EOF_Char;
      Total := Total + 1;
      if Is_Separator(Buffer(I)) then
        In_Word := False;
        if Buffer(I) = LF then -- LF counts toward Total and toward Lines
          Lines := Lines + 1;
        elsif Buffer(I) = CR then -- don't count CR as content or as a line
          Total := Total-1;
        end if;
      else
        if not In_Word then
          Words := Words + 1;
          In_Word := True;
        end if;
      end if;
    end loop;
    exit Through_File when Last < Buffer'Last;
  end loop Through_File;

  T1 := Ada.Calendar.Clock;

  Ada.Text_IO.Put_Line(Natural'Image(Lines)
                       & Natural'Image(Words)
                       & Natural'Image(Total));
  Ada.Text_IO.Put_Line("took" & Duration'Image(T1 - T0));
end Cw;



^ permalink raw reply	[relevance 2%]

* Re: Ada bench : count words
  @ 2005-03-22 12:22  2%             ` Jeff C
  0 siblings, 0 replies; 200+ results
From: Jeff C @ 2005-03-22 12:22 UTC (permalink / raw)


Dmitry A. Kazakov wrote:
> On Tue, 22 Mar 2005 01:16:09 +0000, Marius Amado Alves wrote:
> 
> 
>>I took a shot at the count-words benchmark, a program to count lines, 
>>words and characters. The Ada program currently published there is 
>>broken. My program is correct and portable but:
>>
>>- the speed is circa 1/3 of the GCC C version
>>
>>- it fails to comply with the requirement that the input be taken from 
>>standard input. To implement buffering, I have resorted to 
>>Ada.Direct_IO, which I think cannot apply to standard input.
> 
> 
> Is Text_IO that bad?


It can be. It does a few  things that real programs often do not need to 
do (counting pages) and may not do buffering that is optimal for the job 
here. The problem is of course that it is a requirement to read from 
standard input and if I were running the website I would reject a 
program that does not.

Perhaps this could be done by using ada.text_io.text_streams to get 
access to a stream based on standard input and then use the "Read" 
procedure (v.s. 'read attribute) to get 4k blocks of data (recommended 
chunking size from problem definition). The Read procedure uses an 
"Item" and "Last" approach so you can look for Last to see how much you 
actually read.


Note since Ada 95 came out I hardly ever use direct_io anymore because 
even problems that seem to line up well with direct IO over time degrade 
  as file formats change.

I tend to jump (perhaps to soon) to ada.streams.stream_io approaches and 
or approaches like getting access to text_io streams. Note in this case 
I am not saying that the text_io stream approach will be faster..I dont 
really know..But at least it can be made compliant with the requirements 
of the test.

with Text_IO;
with Ada.Text_IO.Text_Streams;

use Ada.Text_IO.Text_Streams;
use Text_IO;

with Ada.Streams;
use Ada.Streams;

procedure stre_test is


S : Stream_Access := Stream(Standard_Input);

Data : Stream_Element_Array(1 .. 10);
Last : Stream_Element_Offset;
begin

Read(S.all, Data, Last);
Text_IO.Put_Line(Stream_Element_Offset'image(Last));

end stre_test;



^ permalink raw reply	[relevance 2%]

* Re: Advanced file manipulation (multiple question)
  @ 2005-03-01 17:49  1% ` Jeffrey Carter
  0 siblings, 0 replies; 200+ results
From: Jeffrey Carter @ 2005-03-01 17:49 UTC (permalink / raw)


Steph-ADA wrote:

> I'm new on this board so please excuse my lack of habits!
> I have some question about how manipulating files in ADA. Here's a
> kind of list, if you have any informations about how solving these
> problems, it would be very kind!

It's Ada, named for Ada King, Countess Lovelace, who wrote programs for 
  Babbage's Analytical Engine.

> - If I want to copy a file, if it's a 10kb gif file or a big 100Mb avi
> one, should I consider it as binary files, and use the same
> Ada.sequential_io and Ada.direct_io packages? Or is there special
> methods to copy/edit/write in/delete large files?

Probably the best way is to make an OS call for this. That won't be 
portable at the moment, but should be when Ada 0X becomes available, you 
should be able to use Ada.Directories.Copy_File portably.

If you must do this portably in Ada, one way is to use 
Ada.Streams.Stream_IO to open the source file and obtain the size of the 
file, then read and write chunks of the file that will fit in memory. 
When there's not enough data left in the file to fill a chunk, decrease 
the chunk size by a large factor. Repeat until you're copying the last 
few (< 10) bytes byte-by-byte (technically, Stream_Elements, one-by-one).

-- 
Jeff Carter
"Ada has made you lazy and careless. You can write programs in C that
are just as safe by the simple application of super-human diligence."
E. Robert Tisdale
72



^ permalink raw reply	[relevance 1%]

* Re: Ada streams
  2004-12-15 17:26  2% ` Nick Roberts
@ 2004-12-15 19:35  2%   ` tmoran
  0 siblings, 0 replies; 200+ results
From: tmoran @ 2004-12-15 19:35 UTC (permalink / raw)


>Maybe I should say a quick word on what a stream is. In practice, a
>stream is a sequence of bytes -- which are called 'octets' formally --
>which comprise the binary representation of one or a sequence of
>variable values. The values can be of any type. The bytes do not
  Ada.Streams gives a standardized way for the designer of an object
to supply "IO" routines for that object.  Thus Bitmap'Write might in
fact create a JPEG compressed version of an in-memory bitmap array.
If a user creates a composite object he automatically gets an IO
routine that will make the necessary calls for the component parts.
Thus given
  type Stereo_Image_Type is record
    Left, Right : Bitmap;
  end record;
Stereo_Image_Type'Write(F,Scene); will automatically call Bitmap'Write
on the Left and Right images (unless overridden, of course).
  Ada.Streams does not require you to use Ada.Streams.Stream_IO, however,
so you can also create specialized children of Root_Stream_Type which
don't do IO, but rather something else.  You might just want the
Stream_Element_Count of the size of the object, or perhaps a checksum of
its Stream_Element_Array representation.



^ permalink raw reply	[relevance 2%]

* Re: Ada streams
  @ 2004-12-15 17:26  2% ` Nick Roberts
  2004-12-15 19:35  2%   ` tmoran
  0 siblings, 1 reply; 200+ results
From: Nick Roberts @ 2004-12-15 17:26 UTC (permalink / raw)


Daniel Vencler wrote:

> Hi, I want to ask you where I can get good explanation what are and
> how to use (and when) ada streams. There are a few ada tutorials on 
> the net but not single one of them mentions streams.

To answer the question of when to use streams, the brief answer is: in
almost any situation where you are not using text I/O (using the
package Ada.[Wide_]Text_IO and its children), and a few besides.

Consider a variety of different file types in common use today: the
JPEG pictorial image format; the PKWare ZIP compression format; the
Microsoft word processor DOC format; the HTML (HyperText Markup
Language) format used for web pages. For the HTML format, you may wish
to use Ada.Text_IO, but for some rather esoteric (and unfortunate)
technical reasons, you might want to use Ada.Streams.Stream_IO. For
all the others, you will certainly want to use Ada.Streams.Stream_IO.

Similarly, streams will be used to perform packet-based network
communications, and possibly some other kinds of communications. A
package will provide a stream into which you write data into a packet
(it's payload), prior to sending the packet, as well as a stream to
read the (payload) data out of a packet when it is received. A device
driver (interface) package for a printer, say, may well provide a
stream into which you write the data to be sent to the printer.

There are certain rare situations in which you might want to streams
for a purpose other than I/O, for example a memory buffer.

Section 11.12 of the Big Online Book of Linux Ada Programming, as
pointed to by another replier, seems to give quite a good introduction
into how to use streams.

Maybe I should say a quick word on what a stream is. In practice, a
stream is a sequence of bytes -- which are called 'octets' formally --
which comprise the binary representation of one or a sequence of
variable values. The values can be of any type. The bytes do not
normally encode the type (they do if you use the Output procedure on a
tagged type) of each value, nor do they encode what the sequence of
values was (if there was more than one value). You simply have to know
these things to read the values back again correctly. The binary
representation of each type will depend on the target machine, and is
in any case implementation specific. These means that, unless you take
special precautions, you must use the same compiler and target machine
to read a file as you used to write the file in the first place.

Ada.Streams.Stream_IO can be used to read binary files in a standard
format (such as JPEG, ZIP, or DOC), provided you know the exact
details of the formats of all the data types in the format, and use
representation clauses or other methods to read those data types
correctly.

I hope this is helpful. I think you'll have to ask more specific
questions to get more detailed answers.

-- 
Nick Roberts



^ permalink raw reply	[relevance 2%]

* Re: Ada.Streams.Stream_IO.Stream_Access
  2004-11-16 18:52  2%     ` Ada.Streams.Stream_IO.Stream_Access tmoran
@ 2004-11-17  9:31  2%       ` Martin Krischik
  0 siblings, 0 replies; 200+ results
From: Martin Krischik @ 2004-11-17  9:31 UTC (permalink / raw)


tmoran@acm.org wrote:

>>> > Ok, now I try to read from the huge file....and bang I am getting a
>>> > Constraint error. Is this a case that I just can't use ADA Streams on
>>> > files bigger then 2*31 bytes??
>   Works fine for me.  I read a 7GB file in 449,000 16K chunks.  What size
> chunks are you using?
> 
>>Not ADA related, but as a side issue, I am new to 64 bit
>>representation.
>>I understand it is split into High/Low (high-order 32 bits and low
>>order 32 bits
>>representations of the value). At the moment for files 3Gb in size,
>>High
>>is always zero, however, what happens if both High and Low have value?

>   The value is High*2**32+Low

And need to be stored in

type File_Position is range -2**32 .. +2*32-1;
for File_Integer'Size use 64;

or prehaps:

type File_Position is mod 2**64;
for File_Integer'Size use 64;

With Regards

Martin

-- 
mailto://krischik@users.sourceforge.net
http://www.ada.krischik.com



^ permalink raw reply	[relevance 2%]

* Re: Ada.Streams.Stream_IO.Stream_Access
  2004-11-16 18:19  2%   ` Ada.Streams.Stream_IO.Stream_Access Alex
@ 2004-11-16 18:52  2%     ` tmoran
  2004-11-17  9:31  2%       ` Ada.Streams.Stream_IO.Stream_Access Martin Krischik
  0 siblings, 1 reply; 200+ results
From: tmoran @ 2004-11-16 18:52 UTC (permalink / raw)


>> > Ok, now I try to read from the huge file....and bang I am getting a
>> > Constraint error. Is this a case that I just can't use ADA Streams on
>> > files bigger then 2*31 bytes??
  Works fine for me.  I read a 7GB file in 449,000 16K chunks.  What size
chunks are you using?

>Not ADA related, but as a side issue, I am new to 64 bit
>representation.
>I understand it is split into High/Low (high-order 32 bits and low
>order 32 bits
>representations of the value). At the moment for files 3Gb in size,
>High
>is always zero, however, what happens if both High and Low have value?
  The value is High*2**32+Low



^ permalink raw reply	[relevance 2%]

* Re: Ada.Streams.Stream_IO.Stream_Access
  2004-11-16  8:28  2% ` Ada.Streams.Stream_IO.Stream_Access Martin Krischik
@ 2004-11-16 18:19  2%   ` Alex
  2004-11-16 18:52  2%     ` Ada.Streams.Stream_IO.Stream_Access tmoran
  0 siblings, 1 reply; 200+ results
From: Alex @ 2004-11-16 18:19 UTC (permalink / raw)


Martin Krischik <martin@krischik.com> wrote in message news:<8880854.x4B7rzzIl0@linux1.krischik.com>...
> Alex wrote:
> 
> > Hi,
> > 
> > I am having a problem with ADA Streams.
> > 
> > I need to access a file which is >2Gb and read data from it in chunks.
> > 
> > Firstly I was having problems getting the file size as
> > Ada.Streams.Stream_IO.Size didn't seem to want to go over Integer'last
> > (2*31)
> > Worked fine for files up until the 2Gb range and then it went funny!
> > 
> > I had to call a 'c' routine (returned an Integer64...i.e. 2*63) to get
> > the file size and decide how many chunks I wanted.
> > 
> > Ok, now I try to read from the huge file....and bang I am getting a
> > Constraint error. Is this a case that I just can't use ADA Streams on
> > files bigger then 2*31 bytes??
> > 
> > This is driving me nuts and I don't want to call 'c' routines again
> > and spoil my ADA :)
> 
> I take it that you are not a AdaCore customer - otherwise you would not ask
> here. However there is a communication channel for non customer as well:
> "GNAT Discussion List" <gnatlist@lyris.seas.gwu.edu>. You might want to
> raise the point there.
> 
> With Regards
> 
> Martin

Thanks,

I am not an ADACORE custumer, just a frustrated ADA programmer trying
to read from a <2Gb file.

Not ADA related, but as a side issue, I am new to 64 bit
representation.
I understand it is split into High/Low (high-order 32 bits and low
order 32 bits
representations of the value). At the moment for files 3Gb in size,
High
is always zero, however, what happens if both High and Low have value?



^ permalink raw reply	[relevance 2%]

* Re: Ada.Streams.Stream_IO.Stream_Access
  2004-11-16  4:16  5% Ada.Streams.Stream_IO.Stream_Access Alex
  2004-11-16  8:06  2% ` Ada.Streams.Stream_IO.Stream_Access Marius Amado Alves
@ 2004-11-16  8:28  2% ` Martin Krischik
  2004-11-16 18:19  2%   ` Ada.Streams.Stream_IO.Stream_Access Alex
  1 sibling, 1 reply; 200+ results
From: Martin Krischik @ 2004-11-16  8:28 UTC (permalink / raw)


Alex wrote:

> Hi,
> 
> I am having a problem with ADA Streams.
> 
> I need to access a file which is >2Gb and read data from it in chunks.
> 
> Firstly I was having problems getting the file size as
> Ada.Streams.Stream_IO.Size didn't seem to want to go over Integer'last
> (2*31)
> Worked fine for files up until the 2Gb range and then it went funny!
> 
> I had to call a 'c' routine (returned an Integer64...i.e. 2*63) to get
> the file size and decide how many chunks I wanted.
> 
> Ok, now I try to read from the huge file....and bang I am getting a
> Constraint error. Is this a case that I just can't use ADA Streams on
> files bigger then 2*31 bytes??
> 
> This is driving me nuts and I don't want to call 'c' routines again
> and spoil my ADA :)

I take it that you are not a AdaCore customer - otherwise you would not ask
here. However there is a communication channel for non customer as well:
"GNAT Discussion List" <gnatlist@lyris.seas.gwu.edu>. You might want to
raise the point there.

With Regards

Martin


-- 
mailto://krischik@users.sourceforge.net
http://www.ada.krischik.com



^ permalink raw reply	[relevance 2%]

* Re: Ada.Streams.Stream_IO.Stream_Access
  2004-11-16  4:16  5% Ada.Streams.Stream_IO.Stream_Access Alex
@ 2004-11-16  8:06  2% ` Marius Amado Alves
  2004-11-16  8:28  2% ` Ada.Streams.Stream_IO.Stream_Access Martin Krischik
  1 sibling, 0 replies; 200+ results
From: Marius Amado Alves @ 2004-11-16  8:06 UTC (permalink / raw)
  To: comp.lang.ada

> Firstly I was having problems getting the file size as
> Ada.Streams.Stream_IO.Size didn't seem to want to go over Integer'last
> (2*31)

GNAT ties Count to Stream_Element_Offset which is a 32-bit integer on my 
Pentium 3 installation. So I have this problem too, and probably you 
have a similar installation. Maybe there is a GNAT version for 64-bit.






^ permalink raw reply	[relevance 2%]

* Ada.Streams.Stream_IO.Stream_Access
@ 2004-11-16  4:16  5% Alex
  2004-11-16  8:06  2% ` Ada.Streams.Stream_IO.Stream_Access Marius Amado Alves
  2004-11-16  8:28  2% ` Ada.Streams.Stream_IO.Stream_Access Martin Krischik
  0 siblings, 2 replies; 200+ results
From: Alex @ 2004-11-16  4:16 UTC (permalink / raw)


Hi,

I am having a problem with ADA Streams.

I need to access a file which is >2Gb and read data from it in chunks.

Firstly I was having problems getting the file size as
Ada.Streams.Stream_IO.Size didn't seem to want to go over Integer'last
(2*31)
Worked fine for files up until the 2Gb range and then it went funny!

I had to call a 'c' routine (returned an Integer64...i.e. 2*63) to get
the file size and decide how many chunks I wanted.

Ok, now I try to read from the huge file....and bang I am getting a
Constraint error. Is this a case that I just can't use ADA Streams on
files bigger then 2*31 bytes??

This is driving me nuts and I don't want to call 'c' routines again
and spoil my ADA :)

Cheers

Alex



^ permalink raw reply	[relevance 5%]

* Re: excel files
  @ 2004-10-05  1:20  2%   ` Stephen Leake
  0 siblings, 0 replies; 200+ results
From: Stephen Leake @ 2004-10-05  1:20 UTC (permalink / raw)
  To: comp.lang.ada

"stephane richard" <stephane.richard@verizon.net> writes:

> Which brings me to my quest of the day.   What can I use in the Ada 
> hierarchy that will open a file in binary mode and not in sequential text 
> mode?  

Ada.Streams.Stream_IO should do that. But you may need a "form" parameter.

-- 
-- Stephe




^ permalink raw reply	[relevance 2%]

* Re: reading a text file into a string
  2004-07-15 17:59  2% ` Marius Amado Alves
@ 2004-07-15 19:18  0%   ` Nick Roberts
  0 siblings, 0 replies; 200+ results
From: Nick Roberts @ 2004-07-15 19:18 UTC (permalink / raw)


On Thu, 15 Jul 2004 18:59:06 +0100, Marius Amado Alves  
<amado.alves@netcabo.pt> wrote:

> "...is there a more prefered method of reading in a whole text file?"
>
> The preference depends.

That's true, there are many ways to skin a cat, and how you read and  
process the file will very much depend on what you are trying to do.

> The methods are:
>
> - declare a string S of size equal to the file size and
> then call a standard string reading procedure with S as
> the out parameter

The problem with this idea is that there is no standard way to determine  
the size of a text file. For some kinds of text 'file' (such as a device  
or pipe), it may not be possible to tell in advance by any means.

> - use stream attributes 'Read, 'Input of type String and
> facilities in Ada.Streams.Stream_IO

I think this is a terrible idea, unless you know what the character  
encoding is, and wish to do the decoding yourself!

-- 
Nick Roberts



^ permalink raw reply	[relevance 0%]

* Re: reading a text file into a string
  @ 2004-07-15 17:59  2% ` Marius Amado Alves
  2004-07-15 19:18  0%   ` Nick Roberts
  0 siblings, 1 reply; 200+ results
From: Marius Amado Alves @ 2004-07-15 17:59 UTC (permalink / raw)
  To: comp.lang.ada

"...is there a more prefered method of reading in a whole text file?"

The preference depends. The methods are:

- declare a string S of size equal to the file size and then call a 
standard string reading procedure with S as the out parameter

- use stream attributes 'Read, 'Input of type String and facilities in 
Ada.Streams.Stream_IO




^ permalink raw reply	[relevance 2%]

* Re: Stream_Element_Array 2 String
  2004-03-26 18:04  2% ` Marius Amado Alves
@ 2004-03-27  8:24  0%   ` Simon Wright
  0 siblings, 0 replies; 200+ results
From: Simon Wright @ 2004-03-27  8:24 UTC (permalink / raw)


Marius Amado Alves <maa@liacc.up.pt> writes:

> > Im using Ada.Streams.Stream_IO for read block of files and i can convert
> > a Stream_Element_Array to String type.
> > how can i do?
> 
> Ada.Unchecked_Conversion is your friend.
> 
> But make sure you need that, instead of basic stream I/O e.g.
> 
> with Ada.Streams.Stream_IO; use Ada.Streams.Stream_IO;
> 
> procedure Strstr is
>    F : File_Type;
>    S3 : String (1 .. 3);
> begin
>    Create (F);
>    String'Write (Stream (F), "abc");
>    Reset (F);
>    S3 := "***";
>    Set_Mode (F, In_File);
>    String'Read (Stream (F), S3);
>    pragma Assert (S3 = "abc");
> end;

Also, it depends whether performance or clarity is what you need!

There is a third way, using address overlays, which is possibly rather
easier to get wrong .. I always feel uncomfortable with it, but here
goes:

with Ada.Text_IO; use Ada.Text_IO;
with Ada.Unchecked_Conversion;
with Ada.Streams;
with BC.Support.High_Resolution_Time;

procedure String_To_Stream_Element_Array is

   function To_Stream_Element_Array_Using_Unchecked_Conversion
     (S : String) return Ada.Streams.Stream_Element_Array;

   function To_Stream_Element_Array_Using_Overlay
     (S : String) return Ada.Streams.Stream_Element_Array;

   function To_Stream_Element_Array_Using_Unchecked_Conversion
     (S : String) return Ada.Streams.Stream_Element_Array is
      subtype Source is String (S'Range);
      subtype Result is Ada.Streams.Stream_Element_Array
        (Ada.Streams.Stream_Element_Offset (S'First)
           .. Ada.Streams.Stream_Element_Offset (S'Last));
      function To_Array is new Ada.Unchecked_Conversion (Source, Result);
   begin
      return To_Array (S);
   end To_Stream_Element_Array_Using_Unchecked_Conversion;

   function To_Stream_Element_Array_Using_Overlay
     (S : String) return Ada.Streams.Stream_Element_Array is
      Array_View : Ada.Streams.Stream_Element_Array
        (Ada.Streams.Stream_Element_Offset (S'First)
           .. Ada.Streams.Stream_Element_Offset (S'Last));
      for Array_View'Address use S'Address;
   begin
      return Array_View;
   end To_Stream_Element_Array_Using_Overlay;
   
   Start, Finished : BC.Support.High_Resolution_Time.Time;
   Took : Duration;
   
   use type BC.Support.High_Resolution_Time.Time;

begin
   
   Start := BC.Support.High_Resolution_Time.Clock;
   declare
      A : constant Ada.Streams.Stream_Element_Array :=
	To_Stream_Element_Array_Using_Unchecked_Conversion
	("now is the time for all good men"
	   & " to come to the aid of the country"
	   & "now is the time for all good men"
	   & " to come to the aid of the country"
	   & "now is the time for all good men"
	   & " to come to the aid of the country"
	   & "now is the time for all good men"
	   & " to come to the aid of the country"
	   & "now is the time for all good men"
	   & " to come to the aid of the country"
	   & "now is the time for all good men"
	   & " to come to the aid of the country");
   begin
      Finished := BC.Support.High_Resolution_Time.Clock;
      Took := Finished - Start;
   end;
   Put_Line ("unchecked conversion took" & Took'Img);
   
   Start := BC.Support.High_Resolution_Time.Clock;
   declare
      A : constant Ada.Streams.Stream_Element_Array :=
	To_Stream_Element_Array_Using_Overlay
	("now is the time for all good men"
	   & " to come to the aid of the country"
	   & "now is the time for all good men"
	   & " to come to the aid of the country"
	   & "now is the time for all good men"
	   & " to come to the aid of the country"
	   & "now is the time for all good men"
	   & " to come to the aid of the country"
	   & "now is the time for all good men"
	   & " to come to the aid of the country"
	   & "now is the time for all good men"
	   & " to come to the aid of the country");
   begin
      Finished := BC.Support.High_Resolution_Time.Clock;
      Took := Finished - Start;
   end;
   Put_Line ("overlay took" & Took'Img);
   
end String_To_Stream_Element_Array;

Runing on this box (which is a bit antiquated now), I get (GNAT 3.15p)

smaug.pushface.org[64]$ ./string_to_stream_element_array 
Clock rate is 0.400915179 GHz
unchecked conversion took 0.000008465
overlay took 0.000002641


You can find the Booch Components at http://pushface.org/components/bc/.

The high resolution time stuff is for GNAT and Intel (well, "must
support the rdtsc instruction") only.


Shouldn't that be ".. to the aid of the party"? oh well ..


-- 
Simon Wright                               100% Ada, no bugs.



^ permalink raw reply	[relevance 0%]

* Re: Stream_Element_Array 2 String
  2004-03-26 17:30  2% Stream_Element_Array 2 String Shaddow
@ 2004-03-26 18:04  2% ` Marius Amado Alves
  2004-03-27  8:24  0%   ` Simon Wright
  0 siblings, 1 reply; 200+ results
From: Marius Amado Alves @ 2004-03-26 18:04 UTC (permalink / raw)
  To: comp.lang.ada

> Im using Ada.Streams.Stream_IO for read block of files and i can convert
> a Stream_Element_Array to String type.
> how can i do?

Ada.Unchecked_Conversion is your friend.

But make sure you need that, instead of basic stream I/O e.g.

with Ada.Streams.Stream_IO; use Ada.Streams.Stream_IO;

procedure Strstr is
   F : File_Type;
   S3 : String (1 .. 3);
begin
   Create (F);
   String'Write (Stream (F), "abc");
   Reset (F);
   S3 := "***";
   Set_Mode (F, In_File);
   String'Read (Stream (F), S3);
   pragma Assert (S3 = "abc");
end;




^ permalink raw reply	[relevance 2%]

* Stream_Element_Array 2 String
@ 2004-03-26 17:30  2% Shaddow
  2004-03-26 18:04  2% ` Marius Amado Alves
  0 siblings, 1 reply; 200+ results
From: Shaddow @ 2004-03-26 17:30 UTC (permalink / raw)


Hello

Im using Ada.Streams.Stream_IO for read block of files, and i can convert
a Stream_Element_Array to String type.
how can i do?




^ permalink raw reply	[relevance 2%]

* Re: ftp client package
  @ 2003-11-21  8:18  2% ` tmoran
  0 siblings, 0 replies; 200+ results
From: tmoran @ 2003-11-21  8:18 UTC (permalink / raw)


>Yes something like this... and of course with ftp error code
>propagation features (e.g. errors mapped on ada exception ..) ;-)

  -- Error handling:
  -- Some errors will raise exceptions, for instance, Claw.Not_Found_Error
  -- if a socket can't be opened, or Ada.Streams.Stream_IO.Name_Error
  -- on an attempt to Put a non-existent file.  After a Claw.Windows_Error,
  -- call Get_Error_Code to get the ftp socket's error.  (Note that
  -- Claw.Sockets.Image(Error_Code) can return a String description.)
  -- Errors due to unexpected ftp responses will raise Response_Error.
  -- The most recent operation, and its response (the last one if it's
  -- a multi-step operation) are available via Get_Last_Response.



^ permalink raw reply	[relevance 2%]

* Re: Ada.Streams.Stream_IO.File_Type
  2003-07-21  4:03  2%       ` Ada.Streams.Stream_IO.File_Type Nick Roberts
@ 2003-07-21  9:47  2%         ` Robert I. Eachus
  0 siblings, 0 replies; 200+ results
From: Robert I. Eachus @ 2003-07-21  9:47 UTC (permalink / raw)


Nick Roberts wrote:

> I was. Sorry.

No, problem, I knew what you meant.  But someone agreed with your post, 
so I responded to make sure we didn't get snarked:

"Just the place for a Snark!" the Bellman cried,
As he landed his crew with care;
Supporting each man on the top of the tide
By a finger entwined in his hair.
"Just the place for a Snark! I have said it twice:
That alone should encourage the crew.
Just the place for a Snark! I have said it thrice:
What I tell you three times is true."

-- The Hunting of the Snark: an Agony in Eight Fits by Lewis Carroll

(If you never have read it, or haven't read it in ages, it can be found 
in many locations on line. http://oldpoetry.com/volume/164 has 
illustrations by Mervyn Peake another site is 
http://www.snark.de/carroll/snark/)
-- 

                                                        Robert I. Eachus

�In an ally, considerations of house, clan, planet, race are 
insignificant beside two prime questions, which are: 1. Can he shoot? 2. 
Will he aim at your enemy?� -- from the Laiden novels by Sharon Lee and 
Steve Miller.




^ permalink raw reply	[relevance 2%]

* Re: Ada.Streams.Stream_IO.File_Type
  2003-07-20 14:25  2%     ` Ada.Streams.Stream_IO.File_Type Robert I. Eachus
@ 2003-07-21  4:03  2%       ` Nick Roberts
  2003-07-21  9:47  2%         ` Ada.Streams.Stream_IO.File_Type Robert I. Eachus
  0 siblings, 1 reply; 200+ results
From: Nick Roberts @ 2003-07-21  4:03 UTC (permalink / raw)


"Robert I. Eachus" <rieachus@attbi.com> wrote in message
news:3F1AA639.5070200@attbi.com...

> I think that Nick Roberts was thinking of the rule that
> prevents creating a TYPE derived from Ada.Finalization
> .Limited_Controlled other than at the library level from
> having a record extension RM 3.9.1(3) and the note at
> RM 3.9.1(7).

I was. Sorry.

--
Nick Roberts






^ permalink raw reply	[relevance 2%]

* Re: Ada.Streams.Stream_IO.File_Type
  2003-07-20 11:27  2%   ` Ada.Streams.Stream_IO.File_Type Mário Amado Alves
@ 2003-07-20 14:25  2%     ` Robert I. Eachus
  2003-07-21  4:03  2%       ` Ada.Streams.Stream_IO.File_Type Nick Roberts
  0 siblings, 1 reply; 200+ results
From: Robert I. Eachus @ 2003-07-20 14:25 UTC (permalink / raw)


M�rio Amado Alves wrote:
>>...
>>but it could be implemented by putting:
>>
>>   type File_Type is new Ada.Finalization.Limited_Controlled with private;
>>
>>in the private part of package Ada.Streams.Stream_IO. I'm not quite sure if
>>such an implementation would be criticised on the grounds that objects of
>>File_Type could not then be declared other than at library level.

> Indeed it would be criticized by the many of us that find this Ada feature annoying.

So annoying that if there was such a requirement, I am sure that the ARG 
would immediately eliminate it!

I think that Nick Roberts was thinking of the rule that prevents 
creating a TYPE derived from Ada.Finalization.Limited_Controlled other 
than at the library level from having a record extension RM 3.9.1(3) and 
the note at RM 3.9.1(7).  I would like to loosen that up some in Ada 0Y 
to allow derived types of the form:

     type New_T is new tagged T;

in some nested contexts.  But it is probably not a high priority 
extension.  (Note that the declaration above is not currently 
syntactically legal.)  If it were added, though, the key would be 
insuring that there was no distributed overhead.  That's the hard part.

-- 

                                                        Robert I. Eachus

�In an ally, considerations of house, clan, planet, race are 
insignificant beside two prime questions, which are: 1. Can he shoot? 2. 
Will he aim at your enemy?� -- from the Laiden novels by Sharon Lee and 
Steve Miller.




^ permalink raw reply	[relevance 2%]

* Re: Ada.Streams.Stream_IO.File_Type
  2003-07-17 16:01  5% ` Ada.Streams.Stream_IO.File_Type Nick Roberts
@ 2003-07-20 11:27  2%   ` Mário Amado Alves
  2003-07-20 14:25  2%     ` Ada.Streams.Stream_IO.File_Type Robert I. Eachus
  0 siblings, 1 reply; 200+ results
From: Mário Amado Alves @ 2003-07-20 11:27 UTC (permalink / raw)


> ...
> but it could be implemented by putting:
> 
>    type File_Type is new Ada.Finalization.Limited_Controlled with private;
> 
> in the private part of package Ada.Streams.Stream_IO. I'm not quite sure if
> such an implementation would be criticised on the grounds that objects of
> File_Type could not then be declared other than at library level.

Indeed it would be criticized by the many of us that find this Ada feature annoying.



^ permalink raw reply	[relevance 2%]

* Re: Ada.Streams.Stream_IO.File_Type
  2003-07-18 17:34  2%     ` Ada.Streams.Stream_IO.File_Type Matthew Heaney
@ 2003-07-18 18:25  5%       ` David C. Hoos
  0 siblings, 0 replies; 200+ results
From: David C. Hoos @ 2003-07-18 18:25 UTC (permalink / raw)
  To: comp.lang.ada


----- Original Message ----- 
From: "Matthew Heaney" <mheaney@on2.com>
Newsgroups: comp.lang.ada
To: <comp.lang.ada@ada.eu.org>
Sent: Friday, July 18, 2003 12:34 PM
Subject: Re: Ada.Streams.Stream_IO.File_Type


> "Nick Roberts" <nickroberts@blueyonder.co.uk> wrote in message
news:<bf6jhs$b9l6h$1@ID-25716.news.uni-berlin.de>...
> >
> > > Anyone know why it is not in there already?
> >
> > Yes! Because you can use the technique given by David Hoos.
>
> To which technique are you referring?
He's probable referring to my message of July 15 in the thread
"Terminating a Task."
> _______________________________________________
> comp.lang.ada mailing list
> comp.lang.ada@ada.eu.org
> http://ada.eu.org/mailman/listinfo/comp.lang.ada
>




^ permalink raw reply	[relevance 5%]

* Re: Ada.Streams.Stream_IO.File_Type
  2003-07-17 16:42  2%   ` Ada.Streams.Stream_IO.File_Type Nick Roberts
@ 2003-07-18 17:34  2%     ` Matthew Heaney
  2003-07-18 18:25  5%       ` Ada.Streams.Stream_IO.File_Type David C. Hoos
  0 siblings, 1 reply; 200+ results
From: Matthew Heaney @ 2003-07-18 17:34 UTC (permalink / raw)


"Nick Roberts" <nickroberts@blueyonder.co.uk> wrote in message news:<bf6jhs$b9l6h$1@ID-25716.news.uni-berlin.de>...
>
> > Anyone know why it is not in there already?
> 
> Yes! Because you can use the technique given by David Hoos.

To which technique are you referring?



^ permalink raw reply	[relevance 2%]

* Re: Ada.Streams.Stream_IO.File_Type
  2003-07-15 20:13  2% Ada.Streams.Stream_IO.File_Type tmoran
  2003-07-17 15:10  4% ` Ada.Streams.Stream_IO.File_Type Craig Carey
  2003-07-17 16:01  5% ` Ada.Streams.Stream_IO.File_Type Nick Roberts
@ 2003-07-18  7:46  2% ` Dmitry A. Kazakov
  2 siblings, 0 replies; 200+ results
From: Dmitry A. Kazakov @ 2003-07-18  7:46 UTC (permalink / raw)


On Tue, 15 Jul 2003 20:13:37 GMT, tmoran@acm.org wrote:

>Why is this not a descendant of Ada.Finalization.Limited_Controlled?

Probably, because one wished to keep Streams free from tagged types.
(specifications mention only 'Class, but no tagged types).

However, it is brilliant example where interfaces inheritance and
multiple inheritance could be useful: to override a decision made by a
designer, you cannot influence. (:-))

---
Regards,
Dmitry Kazakov
www.dmitry-kazakov.de



^ permalink raw reply	[relevance 2%]

* Re: Ada.Streams.Stream_IO.File_Type
  2003-07-17 15:10  4% ` Ada.Streams.Stream_IO.File_Type Craig Carey
@ 2003-07-17 16:42  2%   ` Nick Roberts
  2003-07-18 17:34  2%     ` Ada.Streams.Stream_IO.File_Type Matthew Heaney
  0 siblings, 1 reply; 200+ results
From: Nick Roberts @ 2003-07-17 16:42 UTC (permalink / raw)


"Craig Carey" <research@ijs.co.nz> wrote in message
news:mt7chvs7heoihdv7a3a6psh5h8v1b46i2i@4ax.com...

> On Tue, 15 Jul 2003 13:30:33 -0500, "David C. Hoos"
> > The package Ada.TextIO.Text_Streams allows one
> > to obtain the stream object corresponding to the
> > standard input -- i.e.:
> >
> > Standard_Input_Stream :
> >    Ada.Text_IO.Text_Streams.Stream_Access :=
> >       Ada.Text_IO.Text_Streams.Stream
> >          (Ada.Text_IO.Standard_Input);
>
> This comment is not on Text_Streams:
> ...
> A fix would be to add this next line to Ada.Streams.Stream_IO:
>
>     function Standard_Input return File_Type;
>
> Anyone know why it is not in there already?

Yes! Because you can use the technique given by David Hoos.

> Portable Ada programs handling piping or CGI I/O may
> need that unless using C (etc.).

If an Ada program which is a client of the Common Gateway Interface (CGI) --
used by various web (HTTP) server programs to allow 'client' programs to
dyamically generate web pages -- implements the interface by directly
interacting with its 'standard input' and 'standard output' (in the Unix
sense), it must be considered essentially non-portable.

Such a program may be portable among Unix-based (maybe POSIX-based)
environments, but generally not otherwise. In this case, the Ada program
might just as well import the appropriate C functions to read or write bytes
directly; I would suggest that in most cases interaction is all text-based
anyway, and it would be easier and better to use Ada.Text_IO (and if the Ada
implementation isn't able to handle line termination correctly, I would say
that's a major problem with the implementation).

For true portability, an Ada program which is intended to be used as a CGI
client should put everything specific to interfacing with the environment
into a package (named 'CGI' perhaps ;-) and I'm fairly sure at least one
such package is available. To port the program to a (significantly
different) environment, this package (only) needs to be reimplemented. This
would provide further advantageous isolation (such as from changes to the
HTTP header that a CGI client program should output).

> ...
> Currently GNAT 3.15's Text_IO.Text_Streams feature
> stops reading, on encountering a ASCII.SUB character
> (= character 10#26#).

That's just a problem with GNAT, isn't it?

> Presumably they don't like the RM's design.

Presumably it's a simple bug in GNAT 3.15. It's quite reasonable (in my
'humble' opinion :-) for text-oriented I/O (except Look_Ahead and
Get_Immediate) to stop on a SUB, but not stream-oriented I/O. The RM permits
this; I think it would often be handy for Ada implementations to provide
options with regard to line, page, and file termination.

--
Nick Roberts
Jabber: debater@charente.de [ICQ: 159718630]






^ permalink raw reply	[relevance 2%]

* Re: Ada.Streams.Stream_IO.File_Type
  2003-07-15 20:13  2% Ada.Streams.Stream_IO.File_Type tmoran
  2003-07-17 15:10  4% ` Ada.Streams.Stream_IO.File_Type Craig Carey
@ 2003-07-17 16:01  5% ` Nick Roberts
  2003-07-20 11:27  2%   ` Ada.Streams.Stream_IO.File_Type Mário Amado Alves
  2003-07-18  7:46  2% ` Ada.Streams.Stream_IO.File_Type Dmitry A. Kazakov
  2 siblings, 1 reply; 200+ results
From: Nick Roberts @ 2003-07-17 16:01 UTC (permalink / raw)


<tmoran@acm.org> wrote in message news:RfZQa.71833$N7.8631@sccrnsc03...

[of the type Ada.Streams.Stream_IO.File_Type]
> Why is this not a descendant of
> Ada.Finalization.Limited_Controlled?

The visible declaration in the package Ada.Streams.Stream_IO is:

   type File_Type is limited private;

This means that the type is not visibly a descendant of Limited_Controlled,
but it could be implemented by putting:

   type File_Type is new Ada.Finalization.Limited_Controlled with private;

in the private part of package Ada.Streams.Stream_IO. I'm not quite sure if
such an implementation would be criticised on the grounds that objects of
File_Type could not then be declared other than at library level.

--
Nick Roberts
Jabber: debater@charente.de [ICQ: 159718630]






^ permalink raw reply	[relevance 5%]

* Re: Ada.Streams.Stream_IO.File_Type
  2003-07-15 20:13  2% Ada.Streams.Stream_IO.File_Type tmoran
@ 2003-07-17 15:10  4% ` Craig Carey
  2003-07-17 16:42  2%   ` Ada.Streams.Stream_IO.File_Type Nick Roberts
  2003-07-17 16:01  5% ` Ada.Streams.Stream_IO.File_Type Nick Roberts
  2003-07-18  7:46  2% ` Ada.Streams.Stream_IO.File_Type Dmitry A. Kazakov
  2 siblings, 1 reply; 200+ results
From: Craig Carey @ 2003-07-17 15:10 UTC (permalink / raw)



On Tue, 15 Jul 2003 20:13:37 GMT, tmoran@acm.org wrote:

---------------------------
>Why is this [Ada.Streams.Stream_IO.File_Type] not a descendant of
>  Ada.Finalization.Limited_Controlled?
---------------------------

That would be done to allow no call to Close(). Close might raise errors.
 GNAT's already code has the doubly linked list (in GNAT-'only' package
 System.File_Control_Block).

---

From another thread (mis)titled "Re: Terminating a task"

It was on the 2nd computer language shootout contest:
  http://dada.perl.it/shootout/  (wc example: counting words in binary)

---------------------------
On Tue, 15 Jul 2003 13:30:33 -0500, "David C. Hoos" 
>The package Ada.TextIO.Text_Streams allows one to obtain the stream
> object corresponding to the standard input -- i.e.:
>
>Standard_Input_Stream : Ada.Text_IO.Text_Streams.Stream_Access =
>   Ada.Text_IO.Text_Streams.Stream (Ada.Text_IO.Standard_Input);
---------------------------

This comment is not on Text_Streams:

---------------------------
From: "Randy Brukardt" <randy@rrsoftware.com>
Newsgroups: comp.lang.ada
Subject: Re: Fill string with multiple lines from standard_input
Date: Fri, 16 Aug 2002 21:26:29 -0500

...
Keep in mind that Stream_IO was virtually untested by the ACATS until
recently, and even now the standard has serious problems which can make
the use of Stream_IO non-portable (since compilers pretty much all do
the wrong thing). So even an implementation which passes the ACATS tests
may still have problems in some cases (having to do with writing, [...]
---------------------------

It is a problem with the design rather than the testing. ACT doesn't
 like the design.

A fix would be to add this next line to Ada.Streams.Stream_IO:

    function Standard_Input return File_Type;

Anyone know why it is not in there already?. Portable Ada programs
 handling piping or CGI I/O may need that unless using C (etc.).

I looked for an AI or comment at Ada-Comment, hinting that a fix is
 desired or intended, but found nothing.

Using C's setmode() and read() seems to be a good solution.

--

Currently GNAT 3.15's Text_IO.Text_Streams feature stops reading, on
 encountering a ASCII.SUB character (= character 10#26#). Presumably
 they don't like the RM's design.

Demo code:   % cat data | tr \\032-\\032 " " | wc
----------------------------------
   type Tio is Ada.Text_IO;
   In_Stream   : Tio.Text_Streams.Stream_Access;
   Out_Stream  : Tio.Text_Streams.Stream_Access;
   Input_Chars : Ada.Streams.Stream_Element_Array (1 .. 1024);
   Last        : Ada.Streams.Stream_Element_Offset;
...
      --  Now use the "do a type conversions on a pointer" package:
   In_Stream := Tio.Text_Streams.Stream (Tio.Current_Input);
   Out_Stream := Tio.Text_Streams.Stream (Tio.Current_Output);
      --  Now use the text package to handle binary I/O:
   loop
      Ada.Streams.Read (In_Stream.all, Input_Chars, Last);
      exit when Last = 0;    --  Quit on the first ASCII.SUB character
      Ada.Streams.Write (Out_Stream.all, Input_Chars (1 .. Last));
   end loop;
----------------------------------


AARM A.12.2: Package Text_IO.Text_Streams:
   http://www.adaic.org/standards/95aarm/html/AA-A-12-2.html

AARM 13.13.1: Package Streams:
   http://www.adaic.org/standards/95aarm/html/AA-13-13-1.html

AARM A.12.1: Package Streams.Stream_IO:
   http://www.adaic.org/standards/95aarm/html/AA-A-12-1.html


______

- Craig Carey

How to Cross-Compiled in FreeBSD to/for a x86 Linux target:
 http://www.ijs.co.nz/code/ada95-freebsd-to-linux-cross-compiler.txt






^ permalink raw reply	[relevance 4%]

* Ada.Streams.Stream_IO.File_Type
@ 2003-07-15 20:13  2% tmoran
  2003-07-17 15:10  4% ` Ada.Streams.Stream_IO.File_Type Craig Carey
                   ` (2 more replies)
  0 siblings, 3 replies; 200+ results
From: tmoran @ 2003-07-15 20:13 UTC (permalink / raw)


Why is this not a descendant of Ada.Finalization.Limited_Controlled?



^ permalink raw reply	[relevance 2%]

* Computer Language Shootout
@ 2003-07-11 12:05  1% Craig Carey
  0 siblings, 0 replies; 200+ results
From: Craig Carey @ 2003-07-11 12:05 UTC (permalink / raw)





The Ada 95 entries have appeared that the new
 "Computer Language Shootout" website:

   http://dada.perl.it/shootout/gnat.html

Ada came first of 32 entries in this OO test:

   http://dada.perl.it/shootout/methcall.html

The Ada entry to read numbers from a file was slow.

The specs for the integer summing program are here: 
   http://www.bagley.org/~doug/shootout/bench/sumcol/

I argue here that the Gcc sumcol entry should be rejected. The C
programmers assumed that the file's lines were known, thus they
knew there was only 100 lines. Speed is not important with 100
lines files, but losing a patch of the competition due to buggy
code from C programmer might easily be more important.

That says programs "can assume" that each line has no more than 128
characters. Thus checking can be omitted and a crash is OK. A quite 
different wording was used in the specs, for lines containing 2
integers.

The specs author, Mr Bagley wrote that the programs "should" read
integers "line by line". The C programmers in fact were never told
whether to use the first integer or the 2nd (if there are two or
more). Also they were required to read an integer when there was
none, which suggests error checking but their C code has none.

I speak for comp.lang.ada and express a pessimism that a C
programmer could recognize that winning arguably bug-infested C
entries ought be disqualified.

-------

As for having 100% of all other entries except my Ada entry, crash due
to bugs, the heapsort test could have been developed into that. Other
programmers had confusion between the 1 that was the result of repeated
halving, with the 1 that was the first index of the array being sorted.

The tester in Italy rejected my regular expression program. It looks
like large programs are getting rejected. That submission used my
strings package. Also entries using Charles code wa rejected. The
tester does not reply readily.

Also the "wc" word count example was small, but that was rejected.
I guess that the tester could not linking in the Windows "_setmode"
and "_read" routines. GNAT has a routine but that is not a standard
like Microsoft C. ('Ada.Streams.Stream_IO.Read (File, Item, Last)' does
not allow File to be associated with the Standard Input so accurate
reading from the console is not a feature of Ada).





Craig Carey

--------------------------

How To Cross-Compile to a Linux target while compiling in a FreeBSD 5
host. Some new instructions are here:
http://www.ijs.co.nz/code/ada95-freebsd-to-linux-cross-compiler.txt






^ permalink raw reply	[relevance 1%]

* Gnat.Sockets.Stream memory "leak"
@ 2003-07-01 19:04  2% Jano
  0 siblings, 0 replies; 200+ results
From: Jano @ 2003-07-01 19:04 UTC (permalink / raw)


Okay, here I go.

I've spent today quite a time tracking down a memory leak. It has 
finally resulted it was exactly not a leak, only a misassumption on my 
part.

It happens that each call to Gnat.Sockets.Stream allocates a new stream 
object to return its access. 

My assumption was that, like the Ada.Streams.Stream_IO.Stream call, that 
Stream_access need not to be freed. Now, I see not any recommendation or 
note about the necessity of freeing these resources neither in Stream_IO 
nor in Gnat.Sockets. I'm mistaken about Stream_IO not needing the free? 
I've been naive about Gnat.Sockets silence about it?

And, as a side note, why doesn't exist a Stream_access type in 
Ada.Streams? I find somewhat inconvenient defining it in my packages and 
converting here and there.

Thanks!

-- 
-------------------------
Jano
402450.at.cepsz.unizar.es
-------------------------



^ permalink raw reply	[relevance 2%]

* Re: AI-248 and counting the elements in an external file
  @ 2003-05-28 18:26  1%                       ` Randy Brukardt
  0 siblings, 0 replies; 200+ results
From: Randy Brukardt @ 2003-05-28 18:26 UTC (permalink / raw)



Larry Kilgallen wrote in message
<$ghCR$mci5sd@eisner.encompasserve.org>...
>In article <vd7hvtd5dkqr17@corp.supernews.com>, "Randy Brukardt"
<randy@rrsoftware.com> writes:
>
>> The intent is that it be well-defined (which might include raising
>> Use_Error if if cannot be figured out, as for a keyboard) for files
that
>> can be read or written by Ada. If Ada doesn't understand the files at
>> all, then we're not trying to say anything.
>>
>> I would expect that this functionality would take more work on some
OSes
>> than it does on Windows or Unix. On the original CP/M, for instance,
you
>> had to figure out the file size by finding out the block size and
>> multiplying it by the number of blocks. That's fine, and keep in mind
>> that this result really is intended to report the physical size of
the
>> file,
>
>The idea of "physical size -- does not have to accurately represent
>size of data contained" was not at all clear to me reading AI-248.
>Is that stated in there, or are there plans for an AI- about AI-248 ?

Why would you expect otherwise? The 'size in Storage_Elements' for a
Direct_IO file certainly doesn't have to be the number of records
(Count) * the size of a record, even though it is often implemented that
way. There may be control information, or (like on the CP/M systems I
mentioned previously), there may be some rounding up. Certainly the
standard has nothing to say about this, and Ada.Directories is not
intended to change anything in this area. It was carefully written with
the intent of not adding any unintended requirements about file
representation, because that would be incompatible, and for no good
reason.

Anyway, AI-248 appears to require that Ada.Directories.Size =
Ada.Streams.Stream_IO.Size for a stream file, but that ought to not have
any implementation burden. But for any file type that is not a stream
file (that is, could not be Created by Stream_IO.Open) (or is a
non-positionable stream file), the meaning of Ada.Directories.Size is
essentially implementation defined, because the standard says nothing
about the representation of Sequential_IO, Text_IO, and Direct_IO files,
and thus the maping to stream elements is not defined by the standard.

You have to remember that the wording part of an AI is written to be
part of the standard. That means if it doesn't say something, that means
that the interpretation is being left to the implementor. It's not
practical to put every possible nuance into an AI; indeed, when I've
done that in the past, I've generally been asked to remove such
discussions as clutter. Too much clutter makes an AI hard to read and
digest.

If you have a specific suggestion for an improvement, I'd be happy to
hear it. (Even better, submit it to Ada-Comment to put it into the
official record.)

                   Randy Brukardt
                   ARG Editor







^ permalink raw reply	[relevance 1%]

* Re: Persistence of limited tagged types
  @ 2003-04-09 10:05  2%   ` Nick Roberts
  0 siblings, 0 replies; 200+ results
From: Nick Roberts @ 2003-04-09 10:05 UTC (permalink / raw)


I hope it won't be taken too amiss that a post a piece of code here.

This little test program is to illustrate the how the 'lifetime' concept (a 
fairly significant concept in computer science these days) applies to the 
persistence of 'live' objects.

A live object is an object which parallels (analogises, models) some 
conceptual or real-world entity, and therefore cannot validly be copied 
(unless it is to model the parallel entity also being duplicated). Live 
objects, therefore (to my mind) correspond, in Ada terms, to a limited type 
(hierarchy).

Live objects, because they cannot just be copied, cannot be directly 
archived or restored, but must first be properly deactivated and 
reactivated, by specific operations that have the correct specific logic 
for each live (limited) type.

In my example 'lifetime' package I have declared roots for the live objects 
(Root_Object) and for a co-hierarchy of their mothballed equivalents 
(Root_Parcel). To deactivate a live object you must call Mothball, and to 
reactivate one you must call Reinstate. (These names may not be the most 
appropriate, but they do at least suggest their function.)

There are many other aspects to the lifetime concept, but the conversion 
between different forms of an object is one of the basic aspects.


----------------------------------------------------------------------
-- Test out lifetime and persistence concepts in Ada.

with Ada.Streams.Stream_IO, Ada.Text_IO, Ada.Unchecked_Deallocation;
use Ada.Streams.Stream_IO, Ada.Text_IO;

procedure Persist1 is


   ------------------------------------------------------------
   package Lifetime is

      type Root_Object is abstract tagged limited private;
      type Object_Ref is access Root_Object'Class;

      type Root_Parcel is abstract tagged private;
      type Parcel_Ref is access Root_Parcel'Class;

      procedure Mothball (Object: in out Root_Object;
                          Parcel: out    Parcel_Ref) is abstract;

      procedure Reinstate (Object: out Object_Ref;
                           Parcel: in  Root_Parcel) is abstract;

   private

      type Root_Object is abstract tagged limited null record;
      type Root_Parcel is abstract tagged null record;

   end Lifetime;


   ------------------------------------------------------------
   package Banking is

      type Active_Account is new Lifetime.Root_Object with private;

      type Dead_Account is new Lifetime.Root_Parcel with private;

      function New_Account (Initial_Balance: in Integer) return 
Lifetime.Object_Ref;

      function Current_Balance (Account: in Active_Account) return Integer;

      procedure Mothball (Active: in out Active_Account;
                          Dead:   out    Lifetime.Parcel_Ref);

      procedure Reinstate (Active: out Lifetime.Object_Ref;
                           Dead:   in  Dead_Account);

   private

      type Active_Account is new Lifetime.Root_Object with
         record
            Balance: Integer;
         end record;

      type Dead_Account is new Lifetime.Root_Parcel with
         record
            Balance: Integer;
         end record;

   end Banking;


   ------------------------------------------------------------
   package body Banking is


      function New_Account (Initial_Balance: in Integer) return 
Lifetime.Object_Ref is

         Account: Lifetime.Object_Ref := new Active_Account;

      begin
         Active_Account(Account.all).Balance := Initial_Balance;
         return Account;
      end;


      function Current_Balance (Account: in Active_Account) return Integer 
is
      begin
         return Account.Balance;
      end;


      procedure Mothball (Active: in out Active_Account;
                          Dead:   out    Lifetime.Parcel_Ref) is
      begin
         -- here need to be actions to suspend the Active account
         Dead := new Dead_Account'( Lifetime.Root_Parcel with Balance => 
Active.Balance );
      end;


      procedure Reinstate (Active: out Lifetime.Object_Ref;
                           Dead:   in  Dead_Account) is
      begin
         Active := new Active_Account;
         Active_Account(Active.all).Balance := Dead.Balance;
         -- here need to be actions to reactivate Active account
      end;


   end banking;


   ------------------------------------------------------------
   type Object_Array is
      array (Positive range <>) of Lifetime.Object_Ref;


   procedure Free is
      new 
Ada.Unchecked_Deallocation(Lifetime.Root_Object'Class,Lifetime.Object_Ref);


   procedure Save (File: in out Ada.Streams.Stream_IO.File_Type;
                   Item: in out Object_Array) is

      Temp: Lifetime.Parcel_Ref;

   begin
      for i in Item'Range loop
         Lifetime.Mothball(Item(i).all,Temp);
         Free(Item(i)); -- make sure it is deallocated
         Lifetime.Root_Parcel'Class'Output(Stream(File),Temp.all);
      end loop;
   end Save;


   procedure Load (File: in out Ada.Streams.Stream_IO.File_Type;
                   Item: out    Object_Array;
                   Last: out    Natural) is

      i: Natural := Item'First-1;

   begin
      while not End_of_File(File) loop
         declare
            subtype LRPC is Lifetime.Root_Parcel'Class;
            Temp: Lifetime.Parcel_Ref := new LRPC'(LRPC'Input(Stream(File))) 
;
         begin
            i := i+1;
            Lifetime.Reinstate(Item(i),Temp.all);
         end;
      end loop;
      Last := i;
   end Load;


   Accounts: Object_Array(1..10);
   Datafile: Ada.Streams.Stream_IO.File_Type;
   Last: Natural;

begin

   Put("Creating test array ...");
   for i in Accounts'Range loop
      Accounts(i) := Banking.New_Account(i);
   end loop;
   Put(" Done.");
   New_Line;

   Put("Saving test array ...");
   Create(Datafile,Out_File,"TESTDAT1.BIN");
   Save(Datafile,Accounts);
   Close(Datafile);
   Put(" Done.");
   New_Line;

   Put("Reloading test array ...");
   Open(Datafile,In_File,"TESTDAT1.BIN");
   Load(Datafile,Accounts,Last);
   Close(Datafile);
   Put(" Done.");
   New_Line;

   Put("Checking test array ...");
   if Last /= Accounts'Last then
      Put(" *** FAILED!");
      goto Final_Stuff;
   end if;      for i in Accounts'Range loop
      if Banking.Current_Balance(Banking.Active_Account(Accounts(i).all)) 
/= i then
         Put(" *** FAILED!");
         goto Final_Stuff;
      end if;
   end loop;
   Put(" Done. Success!");

<<Final_Stuff>>
   New_Line;

end;
----------------------------------------------------------------------


Based on this idea, persistence of a live (limited) type will be done in 
two steps: the deactivation (mothballing) of the live type (derived from 
Root_Object) to get its storable equivalent (derived from Root_Parcel), and 
reactivation (reinstatement) of the stored equivalent to get back to the 
live object; the actual storage and retrieval of the storable (mothballed) 
types.

I think it is important not to confuse the two concepts of 
deactivation/reactivation of live (limited) objects and of persistence 
(which is really just the automatic, or transparent, storage and 
restoration of data).

Of course this little program is only a trivial test of the concept, but I 
think you will find it scales up nicely in practice.

Look particularly at the implementation of the Load and Save procedures, 
and how they use polymorphic (dispatching) calls both to obtain the 
appropriate input and output routines for objects of types derived from 
Root_Parcel and also to obtain the appropriate mothballing and 
reinstatement routines.

Hope this is of interest!


-- 
Nick Roberts
Jabber: debater@charente.de [ICQ: 159718630]



^ permalink raw reply	[relevance 2%]

* Access to T'Class vs T'Class as parameter to subprogram
@ 2003-04-03  7:28  3% Frank
  0 siblings, 0 replies; 200+ results
From: Frank @ 2003-04-03  7:28 UTC (permalink / raw)


Hi!
Regarding GNAT3.15p/Ada95/WindowsXP

In the code below I have done the following:

I have created a tagged type in Basis_Types package, that is abstract
(Abstract_Type). I this basis_types there is a subprogram Do_Something_2
that takes a stream and a pointer to a classwide of Abstract_Type.
I have added subprogram for 'Read attribute to this type.

In Extension_Type I have extended Basis_Type with Extension_Type. I have
added subprograms for 'Read for this new type.

In Initiator.adb I create a pointer to a Extension_Types.Abstract_Type.
Now I try to call "Do_Something_2" with this "pointer to class of extended
abstract_type" This does not compile, because
the compiler expects "pointer to class of basis abstract_type". I can easily
convert the pointer to the expected type, but then the wrong subprogram for
the 'Read attribute is called.

I have done the same approach with Abstract_Type in the two packages. When I
call "Do_Something" with Extension_Type.Abstract_Type from Initiator.adb
this compiles
and the correct subprogram for the 'Read attribute is executed. In
"Do_Something" the formal parameters in Basis_Types are a stream and a
Basis_Types.Abstract_Type'Class.

My issue is: Could I expect that the access-types to a classwide object
behaves as the classwide object themselves?

Does anyone have any comments in addition to what the compiler says? The
compiler says: no :-)

Frank



---------
with Basis_Types;
with Extension_Types;

with Ada.Float_Text_IO;
with Ada.Text_IO;
with Ada.Streams.Stream_IO;

procedure Initiator is

  Object : Extension_Types.Abstract_Type;
  Ptr_Object : Extension_Types.Pointer_To_Abstract_Type;

  Read_File: Ada.Streams.Stream_IO.File_Type;
  Input_Stream : Ada.Streams.Stream_IO.Stream_Access;
begin

  Ada.Streams.Stream_IO.Open(Read_File, Ada.Streams.Stream_IO.In_File,
"Initiator.adb");
  Input_Stream := Ada.Streams.Stream_IO.Stream(Read_File);



-- This works as I expect
  Basis_Types.Do_Something ( Input_Stream, Object);
  Ada.Text_IO.Put_Line("");



-- This I cant make work or I have misunderstood something:-)
  Ptr_Object := new Extension_Types.Abstract_Type;
  Basis_Types.Do_Something_2 ( Input_Stream, Ptr_Object);
-- This compiles but doesnt help me: Basis_Types.Do_Something_2 (
Input_Stream, Basis_Types.Pointer_To_Class_Abstract_Type(Ptr_Object));


  Ada.Streams.Stream_IO.Close(Read_File);
  Ada.Text_IO.Put_Line("");
end Initiator;



-----
with Ada.Streams; use Ada.Streams;

with Basis_Types;

package Extension_Types is


  type Abstract_Type is new Basis_Types.Abstract_Type with null record;
  type Pointer_To_Abstract_Type is access all Abstract_type;
  type Pointer_To_Class_Abstract_Type is access all Abstract_Type'Class;

  procedure Read_Abstract_Type (P_Stream : access Root_Stream_Type'Class;
P_Item : out Abstract_Type);
  for Abstract_Type'Read use Read_Abstract_Type;

  procedure Read_Pointer_To_Class_Abstract_Type (P_Stream : access
Root_Stream_Type'Class;
                                                 P_Item : out
Pointer_To_Class_Abstract_Type);
  for Pointer_To_Class_Abstract_Type'Read use
Read_Pointer_To_Class_Abstract_Type;

end Extension_Types;

-------
with Ada.Text_IO;
with Ada.Streams; use Ada.Streams;

package body Extension_Types is

  procedure Read_Abstract_Type (P_Stream : access Root_Stream_Type'Class;
P_Item : out Abstract_Type) is
  begin
    Ada.Text_IO.Put_Line("Extension_Types.Read_Abstract_Type");
  end Read_Abstract_Type;

  procedure Read_Pointer_To_Class_Abstract_Type (P_Stream : access
Root_Stream_Type'Class;
                                 P_Item : out
Pointer_To_Class_Abstract_Type) is
  begin

Ada.Text_IO.Put_Line("Extension_Types.Read_Pointer_To_Class_Abstract_Type");
  end Read_Pointer_To_Class_Abstract_Type;
end Extension_Types;



----
with Ada.Streams; use Ada.Streams;

package Basis_Types is

  type Abstract_Type is abstract tagged private;
  type Pointer_To_Abstract_Type is access all Abstract_type;
  type Pointer_To_Class_Abstract_Type is access all Abstract_Type'Class;

  procedure Read_Abstract_Type (P_Stream : access Root_Stream_Type'Class;
                                 P_Item : out Abstract_Type);
  for Abstract_Type'Read use Read_Abstract_Type;


  procedure Read_Pointer_To_Class_Abstract_Type (P_Stream : access
Root_Stream_Type'Class;
                                                 P_Item : out
Pointer_To_Class_Abstract_Type);
  for Pointer_To_Class_Abstract_Type'Read use
Read_Pointer_To_Class_Abstract_Type;


  procedure Do_Something ( P_Stream : access Root_Stream_Type'Class;
                             P_Data : out Abstract_Type'Class);
--
  procedure Do_Something_2 ( P_Stream : access Root_Stream_Type'Class;
                             P_Data : out Pointer_To_Class_Abstract_Type);

private

  type Abstract_Type is abstract tagged
    record
      A_Attribute : Integer;
    end record;


end Basis_Types;


-----
with Ada.Text_IO;
with Ada.Streams; use Ada.Streams;

package body Basis_Types is


  procedure Read_Abstract_Type (P_Stream : access Root_Stream_Type'Class;
                                 P_Item : out Abstract_Type) is
  begin
    Ada.Text_IO.Put_Line("Basis_Types.Read_Abstract_Type");
  end Read_Abstract_Type;

  procedure Read_Pointer_To_Class_Abstract_Type (P_Stream : access
Root_Stream_Type'Class;
                                 P_Item : out
Pointer_To_Class_Abstract_Type) is
  begin
    Ada.Text_IO.Put_Line("Basis_Types.Read_Pointer_To_Class_Abstract_Type");
  end Read_Pointer_To_Class_Abstract_Type;

  procedure Do_Something ( P_Stream : access Root_Stream_Type'Class;
                             P_Data : out Abstract_Type'Class) is
  begin
    Ada.Text_IO.Put_Line("Basis_Types.Do_Something");

    Abstract_Type'Class'Read(P_Stream, P_Data);

  end Do_Something;

  procedure Do_Something_2 ( P_Stream : access Root_Stream_Type'Class;
                             P_Data : out Pointer_To_Class_Abstract_Type) is
  begin
    Ada.Text_IO.Put_Line("Basis_Types.Do_Something_2");

    Pointer_To_Class_Abstract_Type'Read(P_Stream, P_Data);

  end Do_Something_2;

end Basis_Types;






^ permalink raw reply	[relevance 3%]

* Re: Getting a symbol table from Gnat 3.15p on Windows
  2003-02-28 20:24  3% ` tmoran
@ 2003-03-01 18:25  0%   ` John R. Strohm
  0 siblings, 0 replies; 200+ results
From: John R. Strohm @ 2003-03-01 18:25 UTC (permalink / raw)


This is probably one of those places where AWK would be a better choice.

Build a file with variable name and type.

Use one AWK script to read that file and write the necessary Ada package
spec to create the variables.

Use another AWK script to read that file and generate the monitoring code
for the variables.

Then your build process ("makefile") runs the AWK scripts when the variable
file changes, and then recompiles the created package spec and monitoring
code.

<tmoran@acm.org> wrote in message news:6AP7a.297368$be.266482@rwcrnsc53...
> Write a source code scanner (ASIS?) to find variables you want to
> monitor/modify.  This should produce as output a package that looks
> like this:
>
> package my_symbols is
>   pragma elaborate_body;
>   global : integer;  -- a line like this for each variable of interest
> end my_symbols;
>
> with ada.streams,
>      ada.streams.stream_io,
>      system;
> package body my_symbols is
>   f : ada.streams.stream_io.file_type;
>   s : ada.streams.stream_io.stream_access;
> begin
>   ada.streams.stream_io.create(f, ada.streams.stream_io.out_file,
>                                "my_symbols.dat");
>   s := ada.streams.stream_io.stream(f);
>   --
>   String'Output(S, "Global");           -- this line pair for each
variable
>   System.Address'Output(S, Global'address);
>   --
>   ada.streams.stream_io.close(f);
> end my_symbols;
>
> Then add "with my_symbols" to your testee program.  Recompilation will
compile
> my_symbols.ads, my_symbols.adb, and testee.adb, which should be pretty
quick.  Then
> Relink and run testee just long enough for elaboration to produce the
> my_symbols.dat file.
>
> my_symbols.dat is your desired symbol table.  Massage it, read it into a
> database, print it in hex, generate source code like
>   Addr_Global : constant System.Address := 16#1234#;
> or whatever.  Your monitor program now has the symbol table and can do
> whatever you want using it.  My_symbols still exists and runs as part of
> elaboration of testee, so addresses don't change, but once it's written
> its output it should have no further effect on the running of testee.





^ permalink raw reply	[relevance 0%]

* Re: Getting a symbol table from Gnat 3.15p on Windows
  @ 2003-02-28 20:24  3% ` tmoran
  2003-03-01 18:25  0%   ` John R. Strohm
  0 siblings, 1 reply; 200+ results
From: tmoran @ 2003-02-28 20:24 UTC (permalink / raw)


Write a source code scanner (ASIS?) to find variables you want to
monitor/modify.  This should produce as output a package that looks
like this:

package my_symbols is
  pragma elaborate_body;
  global : integer;  -- a line like this for each variable of interest
end my_symbols;

with ada.streams,
     ada.streams.stream_io,
     system;
package body my_symbols is
  f : ada.streams.stream_io.file_type;
  s : ada.streams.stream_io.stream_access;
begin
  ada.streams.stream_io.create(f, ada.streams.stream_io.out_file,
                               "my_symbols.dat");
  s := ada.streams.stream_io.stream(f);
  --
  String'Output(S, "Global");           -- this line pair for each variable
  System.Address'Output(S, Global'address);
  --
  ada.streams.stream_io.close(f);
end my_symbols;

Then add "with my_symbols" to your testee program.  Recompilation will compile
my_symbols.ads, my_symbols.adb, and testee.adb, which should be pretty quick.  Then
Relink and run testee just long enough for elaboration to produce the
my_symbols.dat file.

my_symbols.dat is your desired symbol table.  Massage it, read it into a
database, print it in hex, generate source code like
  Addr_Global : constant System.Address := 16#1234#;
or whatever.  Your monitor program now has the symbol table and can do
whatever you want using it.  My_symbols still exists and runs as part of
elaboration of testee, so addresses don't change, but once it's written
its output it should have no further effect on the running of testee.



^ permalink raw reply	[relevance 3%]

* Re: Help needed; Saving access types with sequential_io?
  @ 2003-02-24 17:58  2% ` Rodrigo García
  0 siblings, 0 replies; 200+ results
From: Rodrigo García @ 2003-02-24 17:58 UTC (permalink / raw)


   I would use streams. See if the following code helps you:

with Ada.Streams.Stream_IO; use Ada.Streams.Stream_IO;
with Ada.Text_IO;

procedure Data_Save is
    type A_String is access String;

    type Data_Record is record
       A : A_String;
    end record;

    Saved : Data_Record;
    Loaded : Data_Record;
    F : File_Type;
    S : Stream_Access;
begin
    Create (F, Name => "serialized.txt");
    S := Stream (F);
    Saved.A := new String'("Data saved");
    String'Output (S, Saved.A.all);
    Close (F);

    Open (F, In_File, "serialized.txt");
    S := Stream (F);
    Loaded.A := new String'(String'Input (S));
    Close (F);
    Ada.Text_IO.Put_Line (Loaded.A.all);
end Data_Save;

Rodrigo

khendon wrote:
> Hi all
> 
> I'm a novice in ADA programming, and programming in general. For a
> school project I'm currently working on I'm supposed to create a
> database that needs to have saving/loading functionality. It's all
> very simple stuff, but I'm stuck at the moment, since I don't really
> know how to save the different access types I'm using. The
> informations is saved in records:
> 
> type info;
> type a_info is access info;
> type a_string is access string;
> type info is
>   record
>     a: a_string;
>     b: a_string;
>   end record;
> 
> First, I tried just saving the entire record. That didn't work, my
> guess is because it contains access types, and whatever they're
> currently pointing at disapperas when I shut down the program. So, I
> then thought of saving each string separately. That seemed to work, at
> least the data got saved as it was supposed to. Unfortunately, I'm
> having trouble loading the data from the file into new records that
> will then be added to the database.
> 
> The only way I can think of is to load the data into temporary string,
> and then add those strings to the record. The problem with this is
> that those temporary strings need to have a defined length, so when I
> add them to the record, they will contain lots of garbage I just don't
> want there. That's the whole point of using access types in the record
> in the first place, to be able to save strings of different lengths
> depending on user input.
> 
> If anyone could provide any help I would be most grateful. 
> 
> Regards, Isak





^ permalink raw reply	[relevance 2%]

* Re: Random Access in Ada.Text_IO files
  @ 2003-02-11 18:58  2% ` Stephen Leake
  0 siblings, 0 replies; 200+ results
From: Stephen Leake @ 2003-02-11 18:58 UTC (permalink / raw)


"Micha� Morawski" <morawski@zsk.p.lodz.pl> writes:

> Sometimes, other task try to analyze the log and the task need to read the
> same file.

This is very operating system dependent. There is no guarantee that
Ada.Text_IO files will allow this.

If the two tasks are part of the same program, have them share an
in-memory queue of strings, rather than an external file.

> <snip> and my own module have no acces to stream field of
> File_Type.

If you are writing your own file package, you should not try build it
on top of Text_IO.

You might be able to use Ada.Streams.Stream_IO instead.

-- 
-- Stephe



^ permalink raw reply	[relevance 2%]

* Re: Streams and files
@ 2002-10-14  8:30  0% Grein, Christoph
  0 siblings, 0 replies; 200+ results
From: Grein, Christoph @ 2002-10-14  8:30 UTC (permalink / raw)


> Ada.Streams.Stream_Io.create(file,out_file,"db.txt");
> Stream:=Ada.Streams.Stream_Io.Stream(File);
> while not Ada.Streams.Stream_Io.end_of_file(file) loop

End_of_File is valid for an in_file only.



^ permalink raw reply	[relevance 0%]

* Streams and files
@ 2002-10-14  7:39  3% Sim Con
  0 siblings, 0 replies; 200+ results
From: Sim Con @ 2002-10-14  7:39 UTC (permalink / raw)


Hello! I'd like to write in a file a record and print that file taking
the data's in the record form. I see that these things can be done in
ada using streams but i can't find on the net a good source for learn
how to use it. One problem i have is this:

Ada.Streams.Stream_Io.create(file,out_file,"db.txt");
Stream:=Ada.Streams.Stream_Io.Stream(File);
while not Ada.Streams.Stream_Io.end_of_file(file) loop
....

i receive a mode_error when it process the while line , any help? Thanx
in advance ^_^


-- 
Posted via Mailgate.ORG Server - http://www.Mailgate.ORG



^ permalink raw reply	[relevance 3%]

* Re: Thoughts on the recent ICFP contest
  @ 2002-09-17  3:21  2%         ` Ted Dennison
  0 siblings, 0 replies; 200+ results
From: Ted Dennison @ 2002-09-17  3:21 UTC (permalink / raw)


Wes Groleau wrote:
> What I meant was, I _thought_ that 'Write would put more
> stuff in the stream, and that _another_ call would send
> the assembled stuff to where-ever.

Nope. However, some folk have mentioned making an intermediate stream 
that performs this function (presumably triggered by some kind of 
"flush" call). I have to say, I didn't think of that. I should be 
ashamed of myself, an educated computer scientist, not thinking of 
applying Wheeler's Maxim ("Any problem in computer science can be solved 
with another layer of indirection.")  :-)

However, if you are doing something byte-oriented on a big buffer, the 
'Write calls on each byte alone may chew up a huge amount of time. This 
was touched on in the thread I linked to about disk I/O using 
Ada.Streams.Stream_IO. The underlying transmission mechanisim does 
buffering (as per Robert Dewar), so each 'Write does not actually 
perform an I/O. But still, 'Writing each and every byte took 10 times 
longer than Ada.Streams.Writing the whole buffer when I measured it. 
You'd expect I/O times to dominate over procedure call overhead, even 
for a single I/O, but it doesn't appear to be doing so. (I'm still a 
little doubtful about this, but one has to trust Robert Dewar's word 
about the Gnat internals. :-) )

So what I was talking about doing was creating an object that has a 
'Write and 'Read that are defined to make only one call to 
Ada.Streams.Write and .Read respectively, and that any object can be 
converted into without processing the source object. Any transformation 
done by a 'Write of a lower-level object in an aggregate would not 
happen, but it would be fast for very large aggregates (eg: arrays). You 
can think of it sort of as the System.Address type for streams.

> Obviously, I haven't actually coded any stream stuff.

I found quite a few suprising (to me) things when I first began serious 
stream use. I think its one of those things you really have to do 
yourself once to fully grok.






^ permalink raw reply	[relevance 2%]

* Re: Thoughts on the recent ICFP contest
  @ 2002-09-12 16:43  2%     ` Ted Dennison
    1 sibling, 0 replies; 200+ results
From: Ted Dennison @ 2002-09-12 16:43 UTC (permalink / raw)


Wes Groleau wrote:
> 
>>>to transmit an entire buffer at once, rather than one component at a
>>
>>  Like marshalling all those 'Writes to a buffer, then making one
>>socket'write(buffer) call?
> 
> 
> Have I missed the point all this time?
> I thought that 'Write recursively used
> all the component 'Writes to pack the
> object into a stream, and then the
> possibly dispatching operations of the
> stream would determine the method of
> transmission.

As a point of reference, perhaps you should see this post: 
http://groups.google.com/groups?q=streams+stream_io+group:comp.lang.ada+author:dennison%40telepath.com&hl=en&lr=&ie=UTF-8&oe=UTF-8&selm=94hjbp%24ks6%241%40nnrp1.deja.com&rnum=4
from a couple of years ago.

The issue is that each 'Write on a "leaf object" (a non-compound object) 
will result in its own call to the stream's Write routine. That means if 
I do a 'Write on a 1K string, the stream's Write routine gets called 
1024 times. That's a lot of overhead, not to mention that many stream 
objects might be way more efficient with one Write of 1K than they are 
with 1024 one-byte writes. That is certianly the case with Gnat's 
Ada.Streams.Stream_IO

This issue has come up here many times before. The answer is always that 
the user should either call the stream's Write routine themselves 
directly with the entire buffer, or overload their object's 'Write 
attribute with their own routine that does that.

I'm thinking it would be nice to have an object that does this for you, 
rather than everyone always having to go out and write this same code.




^ permalink raw reply	[relevance 2%]

* Bug in GNAT.Traceback.Symbolic?
@ 2002-08-27 12:29  2% Joachim Schröer
  0 siblings, 0 replies; 200+ results
From: Joachim Schröer @ 2002-08-27 12:29 UTC (permalink / raw)


Hello all,

I have a problem using Gnat.Traceback.Symbolic (Win2000).
A stream based read procedure shall do a 2 step error handling.

First when an error is encountered the reason is appended to
an Exception_Occurrence by Ada.Exceptions.Raise_Exception.
On a higher level were the file object is known a local handler
shall append the filename and the file index to the message by first
retrieving the information including the symbolic stack by

Ada.Exceptions.Exception_Information(E) & 
Gnat.Traceback.Symbolic.Symbolic_Traceback(E)

and then appending the file info and calling Raise_Exception again.

The problem is:
The first call to Symbolic_Traceback does not contain the symbolic 
information.

Appended info:
- Code excerpts
- Stacktrace output using Symbolic_Traceback(E) in the main
- gcc and gnatmake options (gnat.ago)

Is there something else then "-bargs -E" necessary???

----------------------------------------------------------------
   exception
     when Error : others => Add_Info_Close_Reraise(Error, File);
   end Read;

----------------------------------------------------------------

procedure Add_Info_Close_Reraise
            (Error : in     Ada.Exceptions.Exception_Occurrence;
             File  : in out Ada.Streams.Stream_Io.File_Type) is 

begin
   if Ada.Streams.Stream_Io.Is_Open(File) then
     declare
       Name  : constant String  := Ada.Streams.Stream_Io.Name(File);
       Index : constant Natural := 
Natural(Ada.Streams.Stream_Io.Index(File));
       Info  : constant String  := 
Portable.Utils.Exception_Information(Error);
       begin
         Ada.Streams.Stream_Io.Close(File);

         Ada.Exceptions.Raise_Exception
           (E       => Ada.Exceptions.Exception_Identity(Error),
            Message => Info & Os.New_Line &
                       "File: " & Name & ", Index: " & 
Natural'Image(Index));
       end;
     else
       Ada.Exceptions.Reraise_Occurrence(Error);
     end if;
   end Add_Info_Close_Reraise;

----------------------------------------------------------------------------

with Gnat.Traceback.Symbolic;

package body Portable.Utils is
 
---------------------------------------------------------------------------- 

   function Exception_Information(E : in 
Ada.Exceptions.Exception_Occurrence)
            return String is
   begin
     return Ada.Exceptions.Exception_Information(E) &
            Gnat.Traceback.Symbolic.Symbolic_Traceback(E);
   end Exception_Information;
 
---------------------------------------------------------------------------- 

end Portable.Utils;

----------------------------------------------------------------------------
******** First traceback without symbolic info!!!

C:\Ada95\source\Projects\MST_SA\Geo>test_dted_io
E:\dted\DTED\E000\N46.dt1
Exception name: GEO.DTED.IO.DTED_FILE_ERROR

Message: Exception name: GEO.DTED.IO.DTED_FILE_ERROR

Message: unexpected string, '  D' read, expected 'DSI'

File: E:\dted\DTED\E000\N46.dt1, Index:  82

Call stack traceback locations:
0x4488c3 0x44e140 0x4

Call stack traceback locations:
0x449be6 0x450a21 0x410ae0 0x410bc6 0x401401 0x401103 0x77e8ca8e
00449BE6 in geo.dted.io.add_info_close_reraise at geo-dted-io.adb:570
00450A21 in geo.dted.io.read at geo-dted-io.adb:1088
00410AE0 in test_dted_io.test_dted at test_dted_io.adb:86
00410BC6 in test_dted_io at test_dted_io.adb:103
00401401 in ?? at crt1.c:0
00401103 in ?? at crt1.c:0
77E8CA8E in ?? at fake:0
----------------------------------------------------------------------------
******** Only one exception occurrence!!!

C:\Ada95\source\Projects\MST_SA\Geo>test_dted_io
E:\dted\DTED\E000\N46.dt1
Exception name: GEO.DTED.IO.DTED_FILE_ERROR
Message: unexpected string, '  D' read, expected 'DSI'
File: E:\dted\DTED\E000\N46.dt1, Index:  82
Call stack traceback locations:
0x4488c3 0x44e140 0x450a9e 0x410ae0 0x410bc6 0x401401 0x401103 0x77e8ca8e
004488C3 in geo.dted.io.check at geo-dted-io.adb:400
0044E140 in geo.dted.io.read.read at geo-dted-io.adb:937
00450A9E in geo.dted.io.read at geo-dted-io.adb:1082
00410AE0 in test_dted_io.test_dted at test_dted_io.adb:86
00410BC6 in test_dted_io at test_dted_io.adb:103
00401401 in ?? at crt1.c:0
00401103 in ?? at crt1.c:0
77E8CA8E in ?? at fake:0
----------------------------------------------------------------------------
***** gnat options

-O3 -I\ada95\source\lib\math -I\ada95\source\lib\math\arrays 
-I\ada95\source\lib\utilities -I\ada95\source\lib\portable 
-I\ada95\source\lib\portable\posix-win\src 
-I\ada95\compiler\gnat\bindings\win32ada -I\ada95\compiler\gnat\asis 
-I\ada95\source\projects\asis -I\ada95\bin\gnat -I..\mst

-cargs -O3 -bargs -f -E -largs \ada95\compiler\gnat\asis\libasis.a 
\ada95\compiler\gnat\lib\libopengl32.a 
\ada95\compiler\gnat\lib\libglu32.a \ada95\compiler\gnat\lib\libglut32.a 
\ada95\compiler\gnat\lib\libgdi32.a 
\ada95\compiler\gnat\lib\libwsock32.a -I\ada95\source\lib\math 
-I\ada95\source\lib\math\arrays -I\ada95\source\lib\utilities 
-I\ada95\source\lib\portable -I\ada95\source\lib\portable\posix-win\src 
-I\ada95\compiler\gnat\bindings\win32ada -I\ada95\compiler\gnat\asis 
-I\ada95\source\projects\asis -I\ada95\bin\gnat -I..\mst


WINDOWS_TARGET
-----------------------------------------------------------------------------

Thanks for any help
   J. Schr�er




^ permalink raw reply	[relevance 2%]

* Re: Fill string with multiple lines from standard_input
  2002-08-20 18:26  3%           ` Vincent Smeets
  2002-08-20 19:46  0%             ` tmoran
  2002-08-21 12:50  0%             ` Jean-Pierre Rosen
@ 2002-08-21 19:19  0%             ` Randy Brukardt
  2 siblings, 0 replies; 200+ results
From: Randy Brukardt @ 2002-08-21 19:19 UTC (permalink / raw)


Vincent Smeets wrote in message ...
>
>This will bring be back to my other problem. If I use the streams from
>Ada.Text_IO.Text_Streams I will lose the <CR>s.
>
>I can't use Ada.Streams.Stream_IO either because I can't read from the
>standard input with that package. You can only read from files that are
>opened first by Stream_IO.Open call. I would need the following
function
>like in Text_IO:
>    function Standard_Input
>        return Ada.Streams.Stream_IO.File_Type;


That is exactly what Ada.Text_IO.Text_Streams gives you. (I can't
imagine an implementor doing something else...)

Probably your problem is that the OS is eating the <CR>s from Standard
Input, and Ada never sees them. I would expect that you would find this
behavior with any file type that read from the Standard Input handle.

In the mail handling code I've written, I simply assume that the <CR>s
are where they are supposed to be by the RFCs, and put them back in as
needed. Mail that violates RFCs is almost certainly spam anyway; don't
worry about that causing problems, just dump it.

(Bare <CR>s and <LF>s are prohibited by the mail and MIME RFCs anyway,
no mail should have such characters, and what mail servers do with such
mail is undefined. <CR>s paired with <LF>s can always be inserted [and
should be inserted] if you get any bare line ending characters.)

            Randy Brukardt
            (Working on a spam mail filter for the IMS mail server,
written in Ada.)





>Thanks,
>Vincent
>
>





^ permalink raw reply	[relevance 0%]

* Re: Fill string with multiple lines from standard_input
  2002-08-20 18:26  3%           ` Vincent Smeets
  2002-08-20 19:46  0%             ` tmoran
@ 2002-08-21 12:50  0%             ` Jean-Pierre Rosen
  2002-08-21 19:19  0%             ` Randy Brukardt
  2 siblings, 0 replies; 200+ results
From: Jean-Pierre Rosen @ 2002-08-21 12:50 UTC (permalink / raw)


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain, Size: 410 bytes --]


"Vincent Smeets" <No@Spam.org> a �crit dans le message news:
aju1tq$qna$07$1@news.t-online.com...
> I can't use Ada.Streams.Stream_IO either because I can't read from the
> standard input with that package.
But you can with Ada.Text_IO.Text_Streams....

--
---------------------------------------------------------
           J-P. Rosen (rosen@adalog.fr)
Visit Adalog's web site at http://www.adalog.fr





^ permalink raw reply	[relevance 0%]

* Re: Fill string with multiple lines from standard_input
  2002-08-20 18:26  3%           ` Vincent Smeets
@ 2002-08-20 19:46  0%             ` tmoran
  2002-08-21 12:50  0%             ` Jean-Pierre Rosen
  2002-08-21 19:19  0%             ` Randy Brukardt
  2 siblings, 0 replies; 200+ results
From: tmoran @ 2002-08-20 19:46 UTC (permalink / raw)


>If I use the streams from Ada.Text_IO.Text_Streams I will lose the <CR>s.
>
>I can't use Ada.Streams.Stream_IO either because I can't read from the
>standard input with that package. You can only read from files that are
  I suspect your problem is that Standard Input is not opened by the
_OS_ in binary mode, but rather in text mode.  You simply can't use
Standard Input for what you want - you'll have to open a file yourself.



^ permalink raw reply	[relevance 0%]

* Re: Fill string with multiple lines from standard_input
  @ 2002-08-20 18:26  3%           ` Vincent Smeets
  2002-08-20 19:46  0%             ` tmoran
                               ` (2 more replies)
  0 siblings, 3 replies; 200+ results
From: Vincent Smeets @ 2002-08-20 18:26 UTC (permalink / raw)



"Stephen Leake" <stephen.a.leake.1@gsfc.nasa.gov> wrote in message
news:uznvh1snf.fsf@gsfc.nasa.gov...
> "Vincent Smeets" <No@Spam.org> writes:
>
> > As a second release, I want to rewrite my program to work line by line.
This
> > way, I will need to preserve more state in between the processing of the
> > lines, but this will too need the <CR>s as they are in the input stream!
>
> What is the advantage of working "line by line"? If it is to reduce
> the memory usage, then a better approach is to define a stream buffer
> size, and handle the end-of-buffer condition appropriately. "lines"
> don't mean much in this kind of application; in fact, as you have
> seen, using Ada.Text_IO to read lines actually breaks the application.

This will bring be back to my other problem. If I use the streams from
Ada.Text_IO.Text_Streams I will lose the <CR>s.

I can't use Ada.Streams.Stream_IO either because I can't read from the
standard input with that package. You can only read from files that are
opened first by Stream_IO.Open call. I would need the following function
like in Text_IO:
    function Standard_Input
        return Ada.Streams.Stream_IO.File_Type;

Thanks,
Vincent





^ permalink raw reply	[relevance 3%]

* Re: FAQ and string functions
  @ 2002-08-01 14:29  1%     ` Ted Dennison
  0 siblings, 0 replies; 200+ results
From: Ted Dennison @ 2002-08-01 14:29 UTC (permalink / raw)


Oleg Goodyckov <og@videoproject.kiev.ua> wrote in message news:<20020731104643.C1083@videoproject.kiev.ua>...
> strings. In Booch components set in demo files is present file
> bcwords.ada. Look at it. It contains full program for counting and
> printing of frequencies of words met in any given text file. But this file
> - bcwords.ada - begins from 15-line Perl's program, which does the same
> work. Look there, compare volumes of Perl's and Ada's programs, and think,
> why difference is so dramatically big in favor of Perl?

That's odd. All you'd really have to do to do this in Ada would be:
1) Read file into a string
2) Call Ada.Strings.Fixed.Count on the string

Doing 1 could be tricky, if you have no idea how big the file is. But
there are techniques for dealing with that. My personal favorite is
the recursive growing string trick. That only takes about 5 lines of
code. You could also use Ada.Streams.Stream_IO to open and find the
length of the file and String'Read to read it all into one perfectly
sized string.

Doing 2 is a one-liner.

> Perl we say @list=split(/ /,String) and that's all.  Is this Perl's own
> especiality? No. It can be realized in Ada. And I say more - without this

Well, it should be hardly shocking that the "standard" Perl has more
string handling goodies than the standard Ada. Perl was made for
string handling. If it can't even beat a compiled general-purpose
programming language like Ada in this reguard, it should give up its
scripting credentials and go run security in airports or something.

However, you are right that much of this *can* be done in Ada. If you
want more powerful string parsing capabilities, there are lots of
options for you.

One good one (which I see has already been mentioned) is the Gnat
string handling packages. They provide very powerful pattern matching
capability, which is probably the style of working you are used to if
you are a Perl user. The main drawback to this is that it isn't
avilable to you if you are using a compiler other than Gnat (iow: it's
not compiler-portable).

Another, even more powerful option, if you need something really
sophisiticated, is the OpenToken packages
(http://www.telepath.com/~dennison/Ted/OpenToken/OpenToken.html ).
They are written in standard Ada, and should be portable to any
compiler (although there have been minor issues in the past).

> So, by all of diversity of GENERIC string's handling tools in Ada,
> convinient tool is not present.

Well, we are currently looking at beefing up the standard library for
the next version of the language. Perhaps you are saying you believe
string handling needs attention?


-- 
T.E.D.
Home     -  mailto:dennison@telepath.com (Yahoo: Ted_Dennison)
Homepage -  http://www.telepath.com/~dennison/Ted/TED.html



^ permalink raw reply	[relevance 1%]

* Re: Behavior of Stream Attributes On Access Types.
  @ 2002-06-12  3:44  3% ` David C. Hoos, Sr.
  0 siblings, 0 replies; 200+ results
From: David C. Hoos, Sr. @ 2002-06-12  3:44 UTC (permalink / raw)



----- Original Message -----
From: "Marin David Condic ]" <dont.bother.mcondic.auntie.spam@[acm.org>
Newsgroups: comp.lang.ada
To: <comp.lang.ada@ada.eu.org>
Sent: June 10, 2002 2:38 PM
Subject: Behavior of Stream Attributes On Access Types.


> I'm checking section 13.13.2 of the ARM to discover the default behavior of
> the Stream 'Read, 'Write, 'Input and 'Output when they encounter an access
> type. I'm not finding any clear indication of what gets put to the stream -
> although there is a mention in paragraph 35 of raising Constraint_Error on
> input if the value is not of its subtype. Can someone clarify the behavior?
>
> My inclination is to think that the sensible thing would be to call the
> 'Read or 'Write for the thing pointed to by the access type, but this has
> implications for dynamically allocated objects. Will it write/read a
> (totally useless) access value?
>
Here is an example of how I do this in a number of ADT packages I have
developed.

The complete file with appropriate copyright notice, and ratioonale, etc.,
is available at
ftp.ada95.com/pub/access_object_stream_attributes.tgz or
ftp.ada95.com/pub/access_object_stream_attributes.tar.gz

with Ada.Streams.Stream_IO;
with Ada.Text_IO;
with Ada.Unchecked_Deallocation;
procedure Test_Access_Object_Stream_Attributes
is
   type Node;

   type Node_Access is access all Node;

   procedure Node_Access_Read
      (Stream : access Ada.Streams.Root_Stream_Type'Class;
       Item   :    out Node_Access);

   procedure Node_Access_Write
      (Stream : access Ada.Streams.Root_Stream_Type'Class;
       Item   : in     Node_Access);

   type Node is record
      Item : Integer;
      Next : Node_Access;
   end record;

   for Node_Access'Read use Node_Access_Read;

   for Node_Access'Write use Node_Access_Write;

   procedure Node_Access_Read
     (Stream : access Ada.Streams.Root_Stream_Type'Class;
      Item   :    out Node_Access)
   is
      Is_Non_Null : Boolean;
   begin
      Boolean'Read (Stream, Is_Non_Null);
      if Is_Non_Null then
         Item := new Node'(Node'Input (Stream));
      else
         Item := null;
      end if;
   end Node_Access_Read;

   procedure Node_Access_Write
     (Stream : access Ada.Streams.Root_Stream_Type'Class;
      Item   : in     Node_Access)
   is
   begin
      Boolean'Write (Stream, Item /= null);
      if Item /= null then
         Node'Output (Stream, Item.all);
      end if;
   end Node_Access_Write;

   --   NOTE:  Since the Read procedure is an allocator, it is the
   --   responsibility of the caller to deallocate the memory.
   --   To this end, a Deallocate procedure is provided.
   procedure Deallocate (Item : in out Node_Access)
   is
      procedure Free is new Ada.Unchecked_Deallocation
        (Object => Node,
         Name   => Node_Access);
   begin
      if Item.Next /= null then
         -- Not a leaf node; first deallocate node's children,
         -- then deallocate this node
         Deallocate (Item.Next);
         Deallocate (Item);
      else
         -- Leaf node; free the storage
         Free (Item);
      end if;
   end Deallocate;

   Head : Node_Access;
   Tail : Node_Access;
   Next : Node_Access;

   File   : Ada.Streams.Stream_IO.File_Type;
   Stream : Ada.Streams.Stream_IO.Stream_Access;

begin
   -- Link together a few nodes
   for N in 1 .. 10 loop
      if N = 1 then
         Tail := new Node;
         Head := Tail;
      else
         Tail.Next := new Node;
         Tail := Tail.Next;
      end if;
      Tail.Item := N;
   end loop;

   -- Verify the list
   Ada.Text_IO.Put_Line ("Original populated list:");
   Next := Head;
   while next  /= null loop
      Ada.Text_IO.Put_Line (Next.Item'Img);
      Next := Next.Next;
   end loop;

   -- Write the list to a stream file

   -- Create the file
   Ada.Streams.Stream_IO.Create
     (File => File,
      Mode => Ada.Streams.Stream_IO.Out_File,
      Name => "nodes.dat");

   -- Associate a stream with the file
   Stream := Ada.Streams.Stream_IO.Stream (File);

   -- Write the list
   Node_Access'Output (Stream, Head);

   -- Close the file
   Ada.Streams.Stream_IO.Close (File);

   -- Destroy the list
   Deallocate (Head);

   -- Verify the list
   Ada.Text_IO.Put_Line
     ("List after deallocation (should be empty):");
   Next := Head;
   while next  /= null loop
      Ada.Text_IO.Put_Line (Next.Item'Img);
      Next := Next.Next;
   end loop;

   -- Read the list from a stream file

   -- Open the file
   Ada.Streams.Stream_IO.Open
     (File => File,
      Mode => Ada.Streams.Stream_IO.In_File,
      Name => "nodes.dat");

   -- Associate a stream with the file
   Stream := Ada.Streams.Stream_IO.Stream (File);

   -- Read the list
   Head := Node_Access'Input (Stream);

   -- Close the file
   Ada.Streams.Stream_IO.Close (File);

   -- Verify the list
   Ada.Text_IO.Put_Line
     ("List after reading file:");
   Next := Head;
   while next  /= null loop
      Ada.Text_IO.Put_Line (Next.Item'Img);
      Next := Next.Next;
   end loop;

end Test_Access_Object_Stream_Attributes;









^ permalink raw reply	[relevance 3%]

* Re: Grace and Maps (was Re: Development process in the Ada community)
  @ 2002-05-02 15:52  2%                             ` Ted Dennison
  0 siblings, 0 replies; 200+ results
From: Ted Dennison @ 2002-05-02 15:52 UTC (permalink / raw)


"Marin David Condic" <dont.bother.mcondic.auntie.spam@[acm.org> wrote in message news:<aam9tu$9ja$1@nh.pace.co.uk>...
> The spec for the Lists certainly defines some stream operations that
> provides for a solution to persistence as well as communication. Maps ought
> to do the same. Personally, I think it would be handy to have a couple of

That would be my input as well.

> subprograms to explicitly load & store the structure from/to a stream file,
> for the sake of simplicity. Some version of: "Here, I figured out a file for
> you and went and opened it already - you go put/get your data to/from it and
> I don't want to know how you did it..." But maybe that's just me... :-)

Given that Ada.Streams.Stream_IO exists, you pretty much already have
that. If you opened the file using Ada.Streams.Stream_IO.Open (or
.Create), the rest is a one-liner.


-- 
T.E.D.
Home     -  mailto:dennison@telepath.com (Yahoo: Ted_Dennison)
Homepage -  http://www.telepath.com/dennison/Ted/TED.html



^ permalink raw reply	[relevance 2%]

* Re: Another problem with stream reading.
  2002-03-26 17:54  0% ` Warren W. Gay VE3WWG
@ 2002-03-27 15:53  0%   ` Erik Sigra
  0 siblings, 0 replies; 200+ results
From: Erik Sigra @ 2002-03-27 15:53 UTC (permalink / raw)


tisdagen den 26 mars 2002 18.54 skrev du:
> Just shooting from the hip here, I think the problem is that
> you gave the compiler an impossible assignment. By that, I
> mean that you've declared type Byte to have integer range
> 0..255 and at the same time said its size has to be 8 bits.
> There is no room for that range and a sign bit (since it is
> integer here) to exist in 8 bits (you need 9). As a result
> of lying to HAL, HAL decided to disregard your statement
> "for Byte'Size use 8" and used 16 instead.

If you look carefully at my code you can se that i did NOT write "Integer 
range", just "range". And there is certainly no need for a sign bit for the 
range 0 .. 255. If I lie to the compiler, it does certainly not disregard it. 
It complais loudly. If I for example say "for Byte'Size use 7;", it replies
"size for "Byte" too small, minimum allowed is 8"


> If you want signed numbers, you need to fix the range. If
> you want unsigned numbers, then you need a modulo type.

I should not need a modulo type for unsigned numbers. See "Programming in Ada 
95" by John Barnes, 2nd edition, page 552:

	"	For example we can specify the amount of storage to be allocated for
	objects of a type, for the storage pool of an access type and for the working
	storage of a task type. This is done by an attribute definition clause. Thus

		type Byte is range 0 .. 255;
		for Byte'Size use 8;

	indicates that objects of type Byte should occupy only 8 bits. The size of
	individual objects can also be specified."


> Erik Sigra wrote:
> > Now I have the program
> >
> > with Ada;                   use Ada;
> > with Text_IO;               use Text_IO;
> > with Ada.Streams;           use Streams;
> > with Ada.Streams.Stream_IO; use Stream_IO;
> >
> > procedure Streamtest is
> >    The_File : Stream_IO.File_Type;
> > begin
> >    Open (The_File, In_File, "data");
> >    declare
> >       The_Stream : Stream_Access := Stream (The_File);
> >       type Byte is range 0 .. 255;
> >       for Byte'Size use 8;
> >       B : Byte;
> >    begin
> >       while not End_Of_File (The_File) loop
> >          Byte'Read (The_Stream, B);
> >          Put_Line ("Read B = " & B'Img);
> >       end loop;
> >    end;
> > end Streamtest;
> >
> >
> > The data file contains
> > "����" (hexadecimal "ff fe fd fc") (decimal "255 254 253 252). The output
> > of the program is:
> > Read B =  255
> > Read B =  253
> >
> >
> > The problem is that it reads 2 bytes instead of 1 and thus skips each
> > second byte. Why?



^ permalink raw reply	[relevance 0%]

* Re: Another problem with stream reading.
  2002-03-25 18:53  3% Another problem with stream reading Erik Sigra
@ 2002-03-26 17:54  0% ` Warren W. Gay VE3WWG
  2002-03-27 15:53  0%   ` Erik Sigra
  0 siblings, 1 reply; 200+ results
From: Warren W. Gay VE3WWG @ 2002-03-26 17:54 UTC (permalink / raw)


Just shooting from the hip here, I think the problem is that
you gave the compiler an impossible assignment. By that, I
mean that you've declared type Byte to have integer range
0..255 and at the same time said its size has to be 8 bits.
There is no room for that range and a sign bit (since it is
integer here) to exist in 8 bits (you need 9). As a result
of lying to HAL, HAL decided to disregard your statement
"for Byte'Size use 8" and used 16 instead.

If you want signed numbers, you need to fix the range. If
you want unsigned numbers, then you need a modulo type.


Erik Sigra wrote:

> Now I have the program
> 
> with Ada;                   use Ada;
> with Text_IO;               use Text_IO;
> with Ada.Streams;           use Streams;
> with Ada.Streams.Stream_IO; use Stream_IO;
> 
> procedure Streamtest is
>    The_File : Stream_IO.File_Type;
> begin
>    Open (The_File, In_File, "data");
>    declare
>       The_Stream : Stream_Access := Stream (The_File);
>       type Byte is range 0 .. 255;
>       for Byte'Size use 8;
>       B : Byte;
>    begin
>       while not End_Of_File (The_File) loop
>          Byte'Read (The_Stream, B);
>          Put_Line ("Read B = " & B'Img);
>       end loop;
>    end;
> end Streamtest;
> 
> 
> The data file contains
> "����" (hexadecimal "ff fe fd fc") (decimal "255 254 253 252). The output of 
> the program is:
> Read B =  255
> Read B =  253
> 
> 
> The problem is that it reads 2 bytes instead of 1 and thus skips each second 
> byte. Why?
> 


-- 
Warren W. Gay VE3WWG
http://home.cogeco.ca/~ve3wwg




^ permalink raw reply	[relevance 0%]

* Another problem with stream reading.
@ 2002-03-25 18:53  3% Erik Sigra
  2002-03-26 17:54  0% ` Warren W. Gay VE3WWG
  0 siblings, 1 reply; 200+ results
From: Erik Sigra @ 2002-03-25 18:53 UTC (permalink / raw)


Now I have the program

with Ada;                   use Ada;
with Text_IO;               use Text_IO;
with Ada.Streams;           use Streams;
with Ada.Streams.Stream_IO; use Stream_IO;

procedure Streamtest is
   The_File : Stream_IO.File_Type;
begin
   Open (The_File, In_File, "data");
   declare
      The_Stream : Stream_Access := Stream (The_File);
      type Byte is range 0 .. 255;
      for Byte'Size use 8;
      B : Byte;
   begin
      while not End_Of_File (The_File) loop
         Byte'Read (The_Stream, B);
         Put_Line ("Read B = " & B'Img);
      end loop;
   end;
end Streamtest;


The data file contains
"����" (hexadecimal "ff fe fd fc") (decimal "255 254 253 252). The output of 
the program is:
Read B =  255
Read B =  253


The problem is that it reads 2 bytes instead of 1 and thus skips each second 
byte. Why?



^ permalink raw reply	[relevance 3%]

* Re: Read booleans from streams
  2002-03-24 23:18  3% Read booleans from streams Erik Sigra
@ 2002-03-25  3:57  0% ` Eric G. Miller
  0 siblings, 0 replies; 200+ results
From: Eric G. Miller @ 2002-03-25  3:57 UTC (permalink / raw)


In <mailman.1017011702.18089.comp.lang.ada@ada.eu.org>, Erik Sigra wrote:

> I tried to read bytes from a stream and interpret each bit as a Boolean. But
> it did not work as expected. It reads 1 byte for each bit. How should I do
> instead?
> 
> 
> streamtest.adb
> ==============
> with Ada.Text_IO;           use Ada.Text_IO;
> with Ada.Streams;           use Ada.Streams;
> with Ada.Streams.Stream_IO; use Ada.Streams.Stream_IO;
> 
> procedure Streamtest is
>    type Boolean_Aggregate is array (0 .. 7) of Boolean;
>    for Boolean_Aggregate'Component_Size use 1;
> 
>    Current_Byte : Boolean_Aggregate;
> 
>    The_File : Stream_IO.File_Type;
> 
>    The_Stream : Stream_Access;
> 
> begin
> 
>    Open (The_File, In_File, "data");
> 
>    The_Stream := Stream (The_File);
> 
>    loop
>       Boolean_Aggregate'Read (The_Stream, Current_Byte);
>       for I in Boolean_Aggregate'Range loop
>          Put(Current_Byte (I)'Img & ' ');
>       end loop;
>       New_Line;
>    end loop;
> end Streamtest;
> 
> 
> data
> ====
> 02027203
> 
> 
> user > ./streamtest
> FALSE FALSE FALSE FALSE TRUE FALSE FALSE TRUE
> 
> raised ADA.IO_EXCEPTIONS.END_ERROR : s-stratt.adb:170
> 
> 
> I have checked that the size of Boolean_Aggregate is 8 and not 64.

I think the problem is in the read procedure.  It sees an array of 8 elements,
so wants to read 8 bytes.  I think you need a 'Read wrapper to read a single
byte (type Byte is mod 2**8), and then do an Unchecked_Conversion:

   function To_Boolean_Aggregate is new
	Ada.Unchecked_Conversion(Byte,Boolean_Aggregate);

   procedure Read_Boolean_Aggregate
        (Stream : Stream_Access; Data : in out Boolean_Aggregate) is
        
        Item : Byte;
   begin
        Byte'Read (Stream, Item);
        Data := To_Boolean_Aggregate (Item);
   end Read_Boolean_Aggregate;

...

   while not End_Of_File (File_Type) loop
        Read_Boolean_Aggregate (Stream, Data);

        ...
   end loop;



^ permalink raw reply	[relevance 0%]

* Read booleans from streams
@ 2002-03-24 23:18  3% Erik Sigra
  2002-03-25  3:57  0% ` Eric G. Miller
  0 siblings, 1 reply; 200+ results
From: Erik Sigra @ 2002-03-24 23:18 UTC (permalink / raw)


I tried to read bytes from a stream and interpret each bit as a Boolean. But 
it did not work as expected. It reads 1 byte for each bit. How should I do 
instead?


streamtest.adb
==============
with Ada.Text_IO;           use Ada.Text_IO;
with Ada.Streams;           use Ada.Streams;
with Ada.Streams.Stream_IO; use Ada.Streams.Stream_IO;

procedure Streamtest is
   type Boolean_Aggregate is array (0 .. 7) of Boolean;
   for Boolean_Aggregate'Component_Size use 1;

   Current_Byte : Boolean_Aggregate;

   The_File : Stream_IO.File_Type;

   The_Stream : Stream_Access;

begin

   Open (The_File, In_File, "data");

   The_Stream := Stream (The_File);

   loop
      Boolean_Aggregate'Read (The_Stream, Current_Byte);
      for I in Boolean_Aggregate'Range loop
         Put(Current_Byte (I)'Img & ' ');
      end loop;
      New_Line;
   end loop;
end Streamtest;


data
====
02027203


user > ./streamtest
FALSE FALSE FALSE FALSE TRUE FALSE FALSE TRUE

raised ADA.IO_EXCEPTIONS.END_ERROR : s-stratt.adb:170


I have checked that the size of Boolean_Aggregate is 8 and not 64.



^ permalink raw reply	[relevance 3%]

* Re: reading from a file
  @ 2002-02-25 20:46  2%     ` sk
  0 siblings, 0 replies; 200+ results
From: sk @ 2002-02-25 20:46 UTC (permalink / raw)


Hi,

>F is defined as 'text_io.file_type'
>
>i am using Sequentional_io
>
>and the file is open
>
>regards,
>deepie

Use Text_Io functions (Get_Line, Skip_Line etc) on 
"Text_Io.File_Type"

Use Sequential_Io functions on "Sequential_Io.File_Type"

If you really (**REALLY**) need to access text files
sequentially and access sequential files as text, you 
will probably need to use the various Stream abilities.

Ada.Streams;
Ada.Streams.Stream_Io;
Ada.Text_Io.Text_Streams (??? - check actual package name).
...

You also need to watch out for the mode you use to "Open"
a file. Reading from an output file, writing to an input
file, for examples, will bite you.

-------------------------------------
-- Merge vertically for real address
-------------------------------------
s n p @ t . o
 k i e k c c m
------------------------------------



^ permalink raw reply	[relevance 2%]

* Re: How to speed up stream & record handling?
  2002-02-21 12:37  3% How to speed up stream & record handling? Karl Ran
@ 2002-02-24  3:23  3% ` Nick Roberts
  0 siblings, 0 replies; 200+ results
From: Nick Roberts @ 2002-02-24  3:23 UTC (permalink / raw)


On 21 Feb 2002 04:37:57 -0800, karlran1234@yahoo.com (Karl Ran) strongly
typed:

>Hello,
>I've a problem getting a reasonable IO preformance from an Ada
>program (source is attached)
>
>The environment looks like this:
>OS: linux-2.4.16
>CPU: Intel P3/700 MHz / BX chipset
>compiler: gnat-3.14p
>
>The program reads a packet of data (200 bytes) and converts the
>header(2 bytes) to match the architecture.  It will do it 100000 times.
>...

My suggestion (you may not like it!) is: (a) if possible, ensure the
NIC/DMA dumps the data into a useful piece of memory (i.e. shared); (b)
preferably, use assembly.

>It's too slow for the target application.

Which is, please?

>I know the the PC achitecture is known for their bad IO performance,
>but this 2.4 MBytes/s seems not be related to the PC-IO-bottleneck...  

I'm sorry but this is a jaw-dropper. Speak not of that which thou wot not
of, child.

My suggestion for improvements in your Ada code follows.

with Ada.Text_IO;
with Ada.Streams.Stream_IO;

procedure Slow_Ada is

	type Machine_Architecture is (Little_Endian, Big_Endian);

	Architecture: constant Machine_Architecture := Little_Endian; -- IA

   subtype Must_Be_True is Boolean range True..True;

   Check_Element_Size: constant Must_Be_True := 
									Ada.Streams.Stream_Element'Size = 8;

   subtype Data_Array is Ada.Streams.Stream_Element_Array(1..200);

   procedure Adjust_Data (Data: in out Data_Array) is

		Temp: Ada.Streams.Stream_Element; -- assuming this is a byte

   begin
		case Architecture is
			when Little_Endian =>
				Temp      := Data(199); 
				Data(199) := Data(200);
				Data(200) := Temp;
			when Big_Endian =>
				null;
      end case;
   end Adjust_Data;

	pragma Inline(Adjust_Data);

   Item: Data_Array;
   Last: Ada.Streams.Stream_Element_Offset;
   File: Ada.Streams.Stream_IO.File_Type;

begin

   Ada.Streams.Stream_IO.Open
     (Name => "/dev/zero", --use any big file you like (20 MByte)
      File => File,
      Mode => Ada.Streams.Stream_IO.In_File);

   Put("Starting...");

   for I in 1 .. 100000 loop
		--- test for end of file?
		Read(File,Item,Last);
      -- test Last for /= 200?
      Adjust_Data(Item);
		-- do something with the data?
   end loop;

	Put_Line("Done.");

   Ada.Streams.Stream_IO.Close (File);

end Slow_Ada;

If a stream element isn't a byte, you'll need to adjust Adjust_Data (and
remove or change Check_Element_Size). At this (low) level, this sort of
twiddling will always be necessary.

(Also, note how my code does the job with the minimum of 'fuss'.)

Hope this helps.

-- 
Nick Roberts



^ permalink raw reply	[relevance 3%]

* Re: How to speed up stream & record handling?
  @ 2002-02-22 20:25  3% ` tmoran
  0 siblings, 0 replies; 200+ results
From: tmoran @ 2002-02-22 20:25 UTC (permalink / raw)


>How do I avoid calling 'Unsigned_8'Read' 200 times per packet while still
>using streams?
  Go up a level.  Define your own My_Record'Read.  I made an "is new
Ada.Streams.Root_Stream_Type" (see below) and changed the code to:

   procedure My_Record_Read
     (Stream : access Ada.Streams.Root_Stream_Type'Class;
      Item   : out     My_Record) is
      use type Ada.Streams.Stream_Element_Offset;
      The_Data_Bytes : Ada.Streams.Stream_Element_Array (1 .. Data_Array'size/Unsigned_8'Size);
      for The_Data_Bytes'Address use Item.A'Address;
      Last : Ada.Streams.Stream_Element_Offset;
   begin
     Not_Slow.Read(Not_Slow.My_File_Type(Stream.all), The_Data_Bytes, Last);
     if Last /= The_Data_Bytes'last then
       null; -- what to do?
     end if;
     B_And_C'Read(Stream, Item.BC);
   end My_Record_Read;

   My_File : aliased Not_Slow.My_File_Type;
  ...
  Not_Slow.Open(My_File,
      Mode => Ada.Streams.Stream_IO.In_File,
      Name => "r:big");

  for I in 1 .. 100000 loop
      My_Record'Read (My_File'access, Item);
  end loop;

  Not_Slow.Close(My_File);

and it ran in 0.22 seconds.  (Gnat 3.14p, -O2)
Of course the fixed record size makes Sequential_IO still a faster option.

with Ada.Streams,
     Ada.Streams.Stream_IO;
package Not_Slow is

  type My_File_Type is new Ada.Streams.Root_Stream_Type with private;

  procedure Open(Stream : in out My_File_Type;
                 Mode   : in Ada.Streams.Stream_IO.File_Mode;
                 Name   : in String;
                 Form   : in String := "");

  procedure Close(Stream : in out My_File_Type);

  procedure Read(
    Stream : in out My_File_Type;
    Item   :    out Ada.Streams.Stream_Element_Array;
    Last   :    out Ada.Streams.Stream_Element_Offset);

  procedure Write(
    Stream : in out My_File_Type;
    Item   : in     Ada.Streams.Stream_Element_Array);

private

  type My_File_Type is new Ada.Streams.Root_Stream_Type with record
    The_File : Ada.Streams.Stream_IO.File_Type;
  end record;

end Not_Slow;

package body Not_Slow is

  procedure Open(Stream : in out My_File_Type;
                 Mode   : in Ada.Streams.Stream_IO.File_Mode;
                 Name   : in String;
                 Form   : in String := "") is
  begin
    Ada.Streams.Stream_IO.Open(Stream.The_File, Mode, Name, Form);
  end Open;

  procedure Close(Stream : in out My_File_Type) is
  begin
    Ada.Streams.Stream_IO.Close(Stream.The_File);
  end Close;

  procedure Read(
    Stream : in out My_File_Type;
    Item   :    out Ada.Streams.Stream_Element_Array;
    Last   :    out Ada.Streams.Stream_Element_Offset) is
  begin
    Ada.Streams.Stream_IO.Read(Stream.The_File, Item, Last);
  end Read;

  procedure Write(
    Stream : in out My_File_Type;
    Item   : in     Ada.Streams.Stream_Element_Array) is
  begin
    Ada.Streams.Stream_IO.Write(Stream.The_File, Item);
  end Write;

end Not_Slow;



^ permalink raw reply	[relevance 3%]

* How to speed up stream & record handling?
@ 2002-02-21 12:37  3% Karl Ran
  2002-02-24  3:23  3% ` Nick Roberts
  0 siblings, 1 reply; 200+ results
From: Karl Ran @ 2002-02-21 12:37 UTC (permalink / raw)


Hello,
I've a problem getting a reasonable IO preformance from an Ada
program (source is attached)

The environment looks like this:
OS: linux-2.4.16
CPU: Intel P3/700 MHz / BX chipset
compiler: gnat-3.14p

The program reads a packet of data (200 bytes) and converts the
header(2 bytes) to match the architecture.  It will do it 100000 times.

>time ./slow_ada
real    0m8.545s
user    0m8.350s <- looks like it spend all the time in the ada-code!
sys     0m0.070s

Thats 20 MByte / 8.5 seconds = 2.4 MByte/sec

It's too slow for the target application.

Has anyone an idea on how to speed up this progam, other than
throwing more CPU-power at the problem?

OK,
I know the the PC achitecture is known for their bad IO performance,
but this 2.4 MBytes/s seems not be related to the PC-IO-bottleneck...  

Thanks,
Karl   

with Ada.Text_IO;
with Ada.Streams.Stream_IO;
with System;

procedure Slow_Ada is

   type Unsigned_4 is mod 2 **4;
   for Unsigned_4'Size use 4;

   type Unsigned_8 is mod 2 ** 8;
   for Unsigned_8'Size use 8;

   type Unsigned_12 is mod 2 ** 12;
   for Unsigned_12'Size use 12;

   type Data_array is array( 1 .. 198 ) of Unsigned_8;

   -- Because a single byte is occupied by Both part of B and all of C,
   -- We combine them into a record so we can define stream-oriented
   -- attributes such that they can be read and written from/to a stream
   -- properly, regardless of machine endianness.

   type B_And_C is
      record
        B : Unsigned_12;
        C : Unsigned_4;
      end record;

   -- Use this representation clause on a little-endian machine.
   for B_And_C use
     record at mod 1;
        B at 0 range 4 .. 15;
        C at 0 range 0 .. 3;
     end record;

   -- Use this representation clause on a big-endian machine.
--    for B_and_C use
--      record at mod 1;
--         B at 0 range 0 .. 11;
--         C at 0 range 12 .. 15;
--      end record;

   for B_And_C'Size use 16;

   -- We now procedd to declare the stream-orientd attributes
   procedure B_And_C_Read
     (Stream : access Ada.Streams.Root_Stream_Type'Class;
      Item   : out     B_And_C);

   procedure B_And_C_Write
     (Stream : access Ada.Streams.Root_Stream_Type'Class;
      Item   : in     B_And_C);

   for B_And_C'Read use B_And_C_Read;

   for B_And_C'Write use B_And_C_Write;

   type My_Record is
     record
        A  : Data_array; -- 200 bytes
        BC : B_And_C;    --   2 bytes
     end record;

   type Byte_Array is array (Positive range <>) of Unsigned_8;

   -- This procedure reverses the oder of the bytes in its argument.
   procedure Swap (The_Bytes : in out Byte_Array) is
      Temp : Unsigned_8;
   begin
      for B in 1 .. The_Bytes'Last / 2 loop
         Temp := The_Bytes (B);
         The_Bytes (B) := The_Bytes (The_Bytes'Last - B + 1);
         The_Bytes (The_Bytes'Last - B + 1) := Temp;
      end loop;
   end Swap;


   -- These porocedures implement the stream-oriented attributes.
   procedure B_And_C_Read
     (Stream : access Ada.Streams.Root_Stream_Type'Class;
      Item   : out     B_And_C) is
      The_Bytes : Byte_Array (1 .. Item'Size / Unsigned_8'Size);
      for The_Bytes'Address use Item'Address;
      use type System.Bit_Order;
   begin
      Byte_Array'Read (Stream, The_Bytes);
      if System.Default_Bit_Order = System.Low_Order_First then
        Swap (The_Bytes);
      end if;
   end B_And_C_Read;

   procedure B_And_C_Write
     (Stream : access Ada.Streams.Root_Stream_Type'Class;
      Item   : in     B_And_C) is
      The_Bytes : Byte_Array (1 .. Item'Size / Unsigned_8'Size);
      for The_Bytes'Address use Item'Address;
      use type System.Bit_Order;
   begin
      if System.Default_Bit_Order = System.Low_Order_First then
        Swap (The_Bytes);
      end if;
      Byte_Array'Write (Stream, The_Bytes);
   end B_And_C_Write;

   Item : My_Record;

   File : Ada.Streams.Stream_IO.File_Type;

   Stream : Ada.Streams.Stream_IO.Stream_Access;
begin
   Ada.Streams.Stream_IO.Open
     (Name => "/dev/zero", --use any big file you like (20 MByte)
      File => File,
      Mode => Ada.Streams.Stream_IO.In_File);

   Stream := Ada.Streams.Stream_IO.Stream (File);

   for I in 1 .. 100000 loop

      My_Record'Read (Stream, Item);

   end loop;

   Ada.Streams.Stream_IO.Close (File);

end Slow_Ada;



^ permalink raw reply	[relevance 3%]

* Re: Adasockets storage problem
  @ 2002-02-17  7:09  2% ` Simon Wright
  0 siblings, 0 replies; 200+ results
From: Simon Wright @ 2002-02-17  7:09 UTC (permalink / raw)


"Nazgul" <darkelf@aim.homelinux.com> writes:

> I'm using the Adasockets library to have network funcionallity in a
> program.  The problem is, it works fine if the server and the client
> are both running in the same architecture, for example i386, but
> when the server runs in a HP-UX and the client in i386, the client
> raises and STORAGE_ERROR when receiving a string.
> 
> I suppose it's something about little endian/big endian and using
> htons(), htonl(),... like in C, but I don't know how to fix it.

It may well be.

We've used the GLADE version of System.Stream_Attributes, now in
glade-3.14p-src/Garlic/s-stratt.adb - you don't need the full GLADE
runtime, just (!) compile this file on its own (with -gnatg) and link
with it, at each end of your connection. You may need -I- to get the
compilation to actually see this file, and there may be other parts of
the RTL that need recompiling (I think they get compiled with inlining
on, -gnatn, so there's a dependency on s-stratt.adb that you weren't
expecting).

I wouldn't be surprised if this use also affected what happens when
you use Ada.Streams.Stream_IO.



^ permalink raw reply	[relevance 2%]

* Re: Reading from a saved stream
  2002-01-23  4:10  3% Reading from a saved stream Paul Pukite
@ 2002-01-24  6:03  0% ` Greg Bek
  0 siblings, 0 replies; 200+ results
From: Greg Bek @ 2002-01-24  6:03 UTC (permalink / raw)


Paul,
The code looks right and as far as I can tell this is an Apex bug (I tested
on more than
one platform) and the bug appears to be on the reading side of the code.

I tested on our current internal build and the program works correctly.

I suggest you contact Rational support so that they open a case log and
correctly
track the issue.

Greg Bek
gab@rational.com



<puk @ umn._edu_ (Paul Pukite)> wrote in message
news:3c4e2839.2139458@news.tc.umn.edu...
> Is the attached pattern legal & portable Ada? I believe
> so but a compiler upgrade from Rational Apex 3.0.0b
> to Rational Apex 4.0.0b resulted in the following
> questionable output for the Stream_Save main procedure:
>
> Received Move Command with Speed = 259
> Speed should be = 999
>
> The dispatching works OK but the transferred data looks odd.
>
> I would like to know if this is more likely a regression
> bug or if Rational is following the standard leading to
> an unexpected outcome. The results are independent of
> the OS by the way. Also, the same behavior occurs if the
> base class is not labelled abstract.
>
> We have spent a lot of effort creating streamable classes and
> to hit this issue has got me second-guessing this particular idiom.
> Any comments are appreciated.
>
> thanks,
> Paul Pukite
>
> ::::::::::::::
> base.1.ada
> ::::::::::::::
> package Base is
>
>     type Selection is (Zero, One, Two, Three);
>
>     type Item is abstract tagged
> record
>     Menu : Integer := 1;
>     Enum : Selection := Three;
> end record;
>     -- Primitive op
>     procedure Input (Msg : in Item) is abstract;
>
> end Base;
> ::::::::::::::
> gizmo.1.ada
> ::::::::::::::
> with Base;
> package Gizmo is
>     pragma Elaborate_Body;
>
>     type Move is new Base.Item with
> record
>     Speed : Integer := 1;
> end record;
>     procedure Input (Obj : in Move);
>
> end Gizmo;
> ::::::::::::::
> gizmo.2.ada
> ::::::::::::::
> with Text_Io;
>
> package body Gizmo is
>
>     procedure Input (Obj : in Move) is
>     begin
> Text_Io.Put_Line ("Received Move Command with Speed =" &
>   Integer'Image (Obj.Speed));
>     end Input;
>
> end Gizmo;
> ::::::::::::::
> stream_save.2.ada
> ::::::::::::::
> with Ada.Streams.Stream_Io;
> with Text_Io;
> with Base;
> with Gizmo;
>
> procedure Stream_Save is
>     Stream_File_Name : constant String := "stream.out";
>
>     procedure Save (Cmd : in Base.Item'Class) is
> File : Ada.Streams.Stream_Io.File_Type;
> S : Ada.Streams.Stream_Io.Stream_Access;
>     begin
> Ada.Streams.Stream_Io.Create (File, Name => Stream_File_Name);
> S := Ada.Streams.Stream_Io.Stream (File);
> Base.Item'Class'Output (S, Cmd);
> Ada.Streams.Stream_Io.Close (File);
>     end Save;
>
>     procedure Play_Back is
> File : Ada.Streams.Stream_Io.File_Type;
> S : Ada.Streams.Stream_Io.Stream_Access;
>     begin
> Ada.Streams.Stream_Io.Open
>    (File, Ada.Streams.Stream_Io.In_File, Stream_File_Name);
> S := Ada.Streams.Stream_Io.Stream (File);
> Base.Input (Base.Item'Class'Input (S));
> Ada.Streams.Stream_Io.Close (File);
>     end Play_Back;
>
>     Obj : Gizmo.Move;
>     Speed : constant Integer := 999;
> begin
>     Obj.Speed := Speed;
>     Save (Obj);  -- Save the command
>     Play_Back;   -- Play back (and dispatch) the command
>     Text_Io.Put_Line ("Speed should be =" & Integer'Image (Speed));
> end Stream_Save;
>
> pragma Main (Posix_Compliant => False); -- needed for Text_IO.Create
>





^ permalink raw reply	[relevance 0%]

* Reading from a saved stream
@ 2002-01-23  4:10  3% Paul Pukite
  2002-01-24  6:03  0% ` Greg Bek
  0 siblings, 1 reply; 200+ results
From: Paul Pukite @ 2002-01-23  4:10 UTC (permalink / raw)


Is the attached pattern legal & portable Ada? I believe
so but a compiler upgrade from Rational Apex 3.0.0b
to Rational Apex 4.0.0b resulted in the following
questionable output for the Stream_Save main procedure:

Received Move Command with Speed = 259
Speed should be = 999

The dispatching works OK but the transferred data looks odd.

I would like to know if this is more likely a regression 
bug or if Rational is following the standard leading to
an unexpected outcome. The results are independent of
the OS by the way. Also, the same behavior occurs if the
base class is not labelled abstract.

We have spent a lot of effort creating streamable classes and
to hit this issue has got me second-guessing this particular idiom.
Any comments are appreciated.

thanks,
Paul Pukite

::::::::::::::
base.1.ada
::::::::::::::
package Base is

    type Selection is (Zero, One, Two, Three);

    type Item is abstract tagged
	record
	    Menu : Integer := 1;
	    Enum : Selection := Three;
	end record;
    -- Primitive op
    procedure Input (Msg : in Item) is abstract;

end Base;
::::::::::::::
gizmo.1.ada
::::::::::::::
with Base;
package Gizmo is
    pragma Elaborate_Body;

    type Move is new Base.Item with
	record
	    Speed : Integer := 1;
	end record;
    procedure Input (Obj : in Move);

end Gizmo;
::::::::::::::
gizmo.2.ada
::::::::::::::
with Text_Io;

package body Gizmo is

    procedure Input (Obj : in Move) is
    begin
	Text_Io.Put_Line ("Received Move Command with Speed =" &
			  Integer'Image (Obj.Speed));
    end Input;

end Gizmo;
::::::::::::::
stream_save.2.ada
::::::::::::::
with Ada.Streams.Stream_Io;
with Text_Io;
with Base;
with Gizmo;

procedure Stream_Save is
    Stream_File_Name : constant String := "stream.out";

    procedure Save (Cmd : in Base.Item'Class) is
	File : Ada.Streams.Stream_Io.File_Type;
	S : Ada.Streams.Stream_Io.Stream_Access;
    begin
	Ada.Streams.Stream_Io.Create (File, Name => Stream_File_Name);
	S := Ada.Streams.Stream_Io.Stream (File);
	Base.Item'Class'Output (S, Cmd);
	Ada.Streams.Stream_Io.Close (File);
    end Save;

    procedure Play_Back is
	File : Ada.Streams.Stream_Io.File_Type;
	S : Ada.Streams.Stream_Io.Stream_Access;
    begin
	Ada.Streams.Stream_Io.Open
	   (File, Ada.Streams.Stream_Io.In_File, Stream_File_Name);
	S := Ada.Streams.Stream_Io.Stream (File);
	Base.Input (Base.Item'Class'Input (S));
	Ada.Streams.Stream_Io.Close (File);
    end Play_Back;

    Obj : Gizmo.Move;
    Speed : constant Integer := 999;
begin
    Obj.Speed := Speed;
    Save (Obj);  -- Save the command
    Play_Back;   -- Play back (and dispatch) the command
    Text_Io.Put_Line ("Speed should be =" & Integer'Image (Speed));
end Stream_Save;

pragma Main (Posix_Compliant => False); -- needed for Text_IO.Create




^ permalink raw reply	[relevance 3%]

* Re: How to avoid unreferenced objects (mutexes etc)
  @ 2002-01-15 18:59  2%     ` Nick Roberts
  0 siblings, 0 replies; 200+ results
From: Nick Roberts @ 2002-01-15 18:59 UTC (permalink / raw)


"Dmitry A. Kazakov" <dmitry@elros.cbb-automation.de> wrote in message
news:3c429d1c.2624281@News.CIS.DFN.DE...

> ...
> Maybe I should describe the problem. There is a communication channel
> implemented as a tagged type. The base type provides low-level I/O
> operations. It has read and write tasks serving as monitors. The
> problem is with the derived types [potentially an arbitrary number of
> them]. They extend the base type and  provide layered high-level
> operations.

I'm not too keen on this approach, because this way the higher levels do not
'hide away' the lower-level interface. Normally, it would be better for a
distinctly higher-level interface to be based on a different type (not a
derived one).

> Some of them must lock the channel [either read or write
> one]. A "natural" solution would be to extend monitors, but alas tasks
> are not tagged.

But the tagged type could contain a component of a task type.

> An untagged solution requires an increasing number of
> wrapping subroutines [thus run-time penalty].

I really don't understand why there should be a greater time penalty for
this solution. I think possibly this is a misunderstanding that lies at the
heart of your problems.

> A genericity-based
> solution produces a combinatoric explosion of packages used as the
> parameters for other packages etc. They must be instantiated at the
> library level. In other words it is a mess.

I don't really see generics being directly relevant to the problem here.

> So I chose the lesser evil = mutexes with all that nasy problems of
> error recovery, you have pointed. I really do not like it.

Please find below an outline skeleton of what a simple communications
hierarchy might look like in Ada. It is merely a guess at what you need, and
it even then is merely a suggestion of how to do it.

=====
-- Abstract level: hardware devices in general

with Ada.Finalization;
package Devices is
   type Abstract_Device is abstract Limited_Controlled with private;
   procedure Reset (Device: access Abstract_Device) is abstract;
   ...
private
   ...
end Devices;

=====
-- Abstract level: communications devices

package Devices.Communications is
   type Byte_Array is ...;
   type Communication_Device is abstract new Abstract_Device with private;
   procedure Read (Transceiver: access Communication_Device;
                   Data: out Byte_Array;
                   Last: out Natural) is abstract;
   procedure Write (Transceiver: access Communication_Device;
                    Data: in Byte_Array) is abstract;
   ...
private
   ...
end Devices.Communications;

=====
-- Low concrete level: my particular communications hardware

with Devices.Communications;
with My_Stuff.Hardware;
package My_Stuff.My_Comms is
   type My_Comms_Device_X is
      new Devices.Communications.Comuunications_Device with private;
   ...
private
   task type Reception_Monitor is
      entry Read (Data: ...);
      entry Reset (Port: in My_Stuff.Hardware.Port_Number);
      entry Stop;
   end;
   task type Transmission_Monitor is
      entry Write (Data: ...);
      entry Reset (Port: in My_Stuff.Hardware.Port_Number);
      entry Stop;
   end;
   ... etc
   type Communications_Device is abstract new Abstract_Device with
      record
         R_Mon: Reception_Monitor;
         T_Mon: Transmission_Monitor;
         ...
      end record;
   procedure Reset (...);
   procedure Read (...);
   procedure Write (...);
   procedure Initialize (...);
   procedure Finalize (...);
   ...
end My_Stuff.My_Comms;

=====
-- Higher level: a communications facility for application programs

with My_Stuff.My_Comms;
with Ada.Streams.Stream_IO;
package Utility.Intercom is
   type Socket_Type is limited private;
   procedure Open (Socket: in out Socket_Type;
                   Name:   in     String;
                   Form:   in     String := "");
   procedure Reset (Socket: in out Socket_Type);
   procedure Close (Socket: in out Socket_Type);
   function Input_Stream  (Socket: in Socket_Type)
               return Ada.Streams.Stream_IO.Stream_Access;
   function Output_Stream (Socket: in Socket_Type)
               return Ada.Streams.Stream_IO.Stream_Access;
private
   ...
end Utility.Intercom;

=====

Note the embedding of two tasks, R_Mon and T_Mon, acting as input and output
monitor respectively, as components within a tagged type.

These tasks would be programmed to buffer the byte stream passing through
them, so as to help 'smooth out the bumps' that you inevitably get as
differences in the rate at which other tasks will produce or consume data.

On a single-processor system, they will act like passive synchronisation
mechanisms (but that's okay); on a multi-processor system they could
actually help to increase the efficiency (speed) of the overall system,
possibly quite dramatically, because they can be busily receiving and
buffering data (R_Mon) and sending buffered data (T_Mon) while other tasks
are busy doing other things.

Also notice how I use successive derivations from a tagged type to evolve
from an abstract level to a concrete one (where the theme is promises made
and promises kept), but I use different types to evolve from a low level to
a higher one (where the theme is the progressive hiding away of nasty
nitty-gritty details).

Hope this helps in some way.

--
Best wishes,
Nick Roberts






^ permalink raw reply	[relevance 2%]

* Re: Ada way to read/write to character file
  @ 2002-01-09 12:11  1%   ` Nick Roberts
  0 siblings, 0 replies; 200+ results
From: Nick Roberts @ 2002-01-09 12:11 UTC (permalink / raw)


<tmoran@acm.org> wrote in message news:IGN_7.9654$762.80315@rwcrnsc54...

> Given timing, error conditions, dropped lines, and the likelihood
> of non-text data, I wonder how often you would actually want to
> do "sequential text I/O" on an RS232 port.

Timing typically turns out not to be a major problem in most cases. In Ada
95, you can always use an ATC time-out to limit a wait. Typically, in the
case of a dropped line, the user resets (or re-runs) the program. Error
conditions simply cause dropped characters; dropped characters can happen
with files anyway (e.g. the typist mistypes something), and Ada programs can
and should deal with this situation in an appropriate way. In the case of
bidirectional I/O with a device, it will often be possible for the program
to detect a (syntax) error in received data, and remedy the problem by
requesting a resend.

Binary (non-text) data (popping up in amongst text data) is not very likely.
Usually, if you have a character device connected to your port, it will not
send or require binary data without being specifically told to do so. Most
(admittedly not all) character devices will never (need to) send or be sent
binary data. If the implementation (and the underlying OS) can deal with
character I/O of all the characters coded 0 to 255, it may be possible to do
binary I/O this way (albeit a nasty way). Since, in Ada 95, you can obtain
the underlying stream of an open text file, this -- or the direct use of
Ada.Streams.Stream_IO -- could be another (better) way to do serial binary
I/O.

Finally, both MS-DOS and the Unixen have all manner of sequential character
'devices' which are not actually serial communications devices (or devices
at all).

It is true that the Ada.Text_IO interface will sometimes be inadequate for
character device I/O, but only sometimes. Things like line and page numbers
might not work properly or meaningfully (but can generally be ignored
anyway). It might be necessary to do a lot of Flushing (but the equivalent
of this is generally necessary for device I/O anyway). (The lack of a
standard Flush was an annoying problem in Ada 83.)

> There's also the question of where do you specify parity & baud rate.

In the 'Form' parameter of the 'Open' procedure, if necessary. An
alternative can be an environment variable, or a system program/function
invoked before the Ada program.

> It's not hard to write a package to do buffered input and output,
> though it varies quite a lot across OSes.

Buffered input and output is usually required in the implementation of
Ada.Text_IO anyway, for ordinary files as well as devices. Thus it makes
sense for the device I/O to be implemented in the same place as the file
I/O, so that the buffering part (at the least) can be shared.

> It may also be that the compiler vendor has supplied one solution.

But this will be non-standard. The whole question was of having a standard
way of doing it.

--
Best wishes,
Nick Roberts






^ permalink raw reply	[relevance 1%]

* Re: Text_IO.End_Of_File Problem
  2001-11-26 18:00  1%     ` Nick Roberts
@ 2001-11-27  9:51  0%       ` Hambut
  0 siblings, 0 replies; 200+ results
From: Hambut @ 2001-11-27  9:51 UTC (permalink / raw)


"Nick Roberts" <nickroberts@adaos.worldonline.co.uk> wrote in message news:<9tu05r$4ua5t$1@ID-25716.news.dfncis.de>...
> Sequential_IO is definitely not what you require. 

Perhaps not. It seemed attractive because it doesn't add line ends in,
which would mean that I wouldn't have to strip off the 'CRLF's
returned from the server.  Basically laziness on my part.

I assume you're definitely against the use of sequential_io in this
case is because there's no guarantee (within the standard?) that
text_io would be able to sensibly read it back.  Which seems sensible
in general.

Cheers for the help. I'll no doubt be back with other daft questions.

<snip>

> 
> When you come to writing out the attachments, for those which produce binary
> data you will need to use Ada.Streams.Stream_IO to write out the binary
> data.
> 

A good point.

cheers,

Hambut



^ permalink raw reply	[relevance 0%]

* Re: Text_IO.End_Of_File Problem
  @ 2001-11-26 18:00  1%     ` Nick Roberts
  2001-11-27  9:51  0%       ` Hambut
  0 siblings, 1 reply; 200+ results
From: Nick Roberts @ 2001-11-26 18:00 UTC (permalink / raw)


Sequential_IO is definitely not what you require. What I need to know now is
how you are getting text from your POP3 server.

If you are able to read text lines from the server, like this:

   Text: String(1..1024); -- arbitrary length
   Last: Natural;
...
   Get_Line(Server,Text,Last);

with the line ends (almost certainly CRLFs) dealt with correctly, you should
have no trouble transferring to a text file, e.g.:

   loop
      if End_of_File(Server) then
         -- deal with premature termination
      end if; -- or catch End_Error
      Get_Line(Server,Text,Last);
      exit when Last=1 and Text(1)='.';
      Put_Line(Temp,Text(1..Last));
   end loop;

regardless of how many blank lines there may be. Of course this must be
preceded and followed by code that sends the right commands to the server (I
forget the commands now, I'm stretching my memory back 10 years as it is ;-)
and interprets its response codes.

Don't forget to close or reset the Temp file. E.g.:

   Close(Temp); -- after writing to it
...
   Open(Temp,In_File,Temp_Name);
   -- now process it for attachments

If your code is just getting TCP segments (rather than whole lines), I
suggest you need a buffer task to deliver actual lines to your main code.

When you come to writing out the attachments, for those which produce binary
data you will need to use Ada.Streams.Stream_IO to write out the binary
data.

Happy to give more detail on any point, if you require.

Does any of this help you?

--
Best wishes,
Nick Roberts


> > (2) WHAT do you really want to do?
> >
>
> What I really want to do is fairly trivial really (or at least should
> be), and involves downloading an email, writing it into a file, and
> then parsing the email to extract attachments etc.  Currently I'm
> downloading the email and saving it into a temporary file, and then
> later opening it to pull out the attachment.  Perhaps my real problem
> is using text_io to write POP3-type output straight to a file (it adds
> a load of superfluous line ends I guess), in which case Sequential_IO
> looks more hopeful.






^ permalink raw reply	[relevance 1%]

* Re: List container strawman 1.1
  @ 2001-11-09 15:55  2%       ` Ted Dennison
  0 siblings, 0 replies; 200+ results
From: Ted Dennison @ 2001-11-09 15:55 UTC (permalink / raw)


In article <3BEACA5A.9030100@acm.org>, Roy Bell says...
>> Roy Bell <rmbell@acm.org> wrote in message news:3BE7DA00.8020807@acm.org...
>> 
>>>>
>>>>with Ada.Finalization;
>>>>with Ada.Streams;
>>>>
>>>>
>>>Can we defer the routines that require Ada.Streams to a child unit?
>
>All of the other proposed additions/deletions are insignificant by 
>comparison. I have seen 100s of Kbytes added to the size of the 
>executable when IO is used.

I don't believe there is any I/O in Ada.Streams. Perhaps you are thinking of
Ada.Streams.Stream_IO?

The problem with putting stuff in a child is that Ada rules would require it to
be a generic as well. That would lead to the situation where proper use requires
instantiating the first package, then using *it* (not the generic but the
instantiation of it) to instantiate the second package. Its not too horrible one
you figure it out. But this is exactly what Booch does that everyone is saying
is unacceptable. So I feel that we really need to avoid using child packages
unless there is a compelling reason.

---
T.E.D.    homepage   - http://www.telepath.com/dennison/Ted/TED.html

No trees were killed in the sending of this message. 
However a large number of electrons were terribly inconvenienced.



^ permalink raw reply	[relevance 2%]

* Re: List container strawman 1.1
  2001-11-05 16:01  2% ` Marin David Condic
  2001-11-05 20:06  2%   ` Ted Dennison
@ 2001-11-05 22:37  0%   ` Nick Roberts
  1 sibling, 0 replies; 200+ results
From: Nick Roberts @ 2001-11-05 22:37 UTC (permalink / raw)


But this can be done, and should be done, by declaring 'read' and 'write'
procedures for the List_Type, conforming to what RM95 13.13.2 requires, and
then using representation clauses to replace the default List_Type'Read and
List_Type'Write attributes. This way, the required behaviour becomes
implicit and automatic.

--
Nick Roberts


"Marin David Condic" <dont.bother.mcondic.auntie.spam@[acm.org> wrote in
message news:9s6d45$bd2$1@nh.pace.co.uk...
> Just to toss in one more bit of feature-creep:
>
> procedure Load (
>     File    : in out Ada.Streams.Stream_IO.File_Type ;
>     Subject : out List) ;
>
> procedure Store (
>     File    : in out Ada.Streams.Stream_IO.File_Type ;
>     Subject : in List) ;
>
>
> I'm presuming that the user can handle file management and keep track of
> which list(s) they have put into the stream file and in what order.
> (Dangerous, but so is life in general...) Under it lies some version of
> 'Input and 'Output to the stream file.
>
> It might similarly have some advantage to have something like:
>
> procedure Put (
>     Subject  : in     List
>     Bytes    :    out Ada.Streams.Stream_Element_Array) ;
>
> procedure Get (
>     Subject  :    out List
>     Bytes    : in     Ada.Streams.Stream_Element_Array) ;






^ permalink raw reply	[relevance 0%]

* Re: List container strawman 1.1
  2001-11-05 20:06  2%   ` Ted Dennison
@ 2001-11-05 20:45  0%     ` Marin David Condic
  0 siblings, 0 replies; 200+ results
From: Marin David Condic @ 2001-11-05 20:45 UTC (permalink / raw)


Oh, just convenience and simplicity I guess. Not sure what the "correct"
idiom should be here. I regularly confuse myself in trying to re-remember
exactly how Streams are supposed to behave and hiding that under a
relatively straightforward procedure seems to free up those brain cells.
After all, the calls I outlined pretty much say what is supposed to happen:
"Get this list out of this file" or "Put this list into this file" in much
the same way one would view "Put_Line (Somefile, Somestring) ;"

I could see getting there via the Stream_Read and Stream_Write as you
outlined. It just seems to require more brain cells to get there. Probably
more flexible, so I wouldn't want to see them go away. I guess its more a
matter of taste than an engineering question.

I'm not married to the idea so if there are really strong objections, I
wouldn't be hurt if it found its way into the bit bucket. It would be
interesting to know if other folks would prefer the Load/Store I suggested
(in conjunction with the Stream_Read/Write) or just the Stream_Read/Write.

MDC

Marin David Condic
Senior Software Engineer
Pace Micro Technology Americas    www.pacemicro.com
Enabling the digital revolution
e-Mail:    marin.condic@pacemicro.com
Web:      http://www.mcondic.com/


"Ted Dennison" <dennison@telepath.com> wrote in message
news:AjCF7.13578$xS6.18106@www.newsranger.com...
>
> What's wrong with the Stream_Read and Stream_Write routines? You can get
from
> those to your version with one call to Ada.Streams.Stream_IO.Stream (File)
>






^ permalink raw reply	[relevance 0%]

* Re: List container strawman 1.1
  2001-11-05 16:01  2% ` Marin David Condic
@ 2001-11-05 20:06  2%   ` Ted Dennison
  2001-11-05 20:45  0%     ` Marin David Condic
  2001-11-05 22:37  0%   ` Nick Roberts
  1 sibling, 1 reply; 200+ results
From: Ted Dennison @ 2001-11-05 20:06 UTC (permalink / raw)


In article <9s6d45$bd2$1@nh.pace.co.uk>, Marin David Condic says...
>
>Just to toss in one more bit of feature-creep:
>
>procedure Load (
>    File    : in out Ada.Streams.Stream_IO.File_Type ;
>    Subject : out List) ;
>
>procedure Store (
>    File    : in out Ada.Streams.Stream_IO.File_Type ;
>    Subject : in List) ;

What's wrong with the Stream_Read and Stream_Write routines? You can get from
those to your version with one call to Ada.Streams.Stream_IO.Stream (File)

---
T.E.D.    homepage   - http://www.telepath.com/dennison/Ted/TED.html

No trees were killed in the sending of this message. 
However a large number of electrons were terribly inconvenienced.



^ permalink raw reply	[relevance 2%]

* Re: List container strawman 1.1
  @ 2001-11-05 16:01  2% ` Marin David Condic
  2001-11-05 20:06  2%   ` Ted Dennison
  2001-11-05 22:37  0%   ` Nick Roberts
    1 sibling, 2 replies; 200+ results
From: Marin David Condic @ 2001-11-05 16:01 UTC (permalink / raw)


Just to toss in one more bit of feature-creep:

procedure Load (
    File    : in out Ada.Streams.Stream_IO.File_Type ;
    Subject : out List) ;

procedure Store (
    File    : in out Ada.Streams.Stream_IO.File_Type ;
    Subject : in List) ;


I'm presuming that the user can handle file management and keep track of
which list(s) they have put into the stream file and in what order.
(Dangerous, but so is life in general...) Under it lies some version of
'Input and 'Output to the stream file.

It might similarly have some advantage to have something like:

procedure Put (
    Subject  : in     List
    Bytes    :    out Ada.Streams.Stream_Element_Array) ;

procedure Get (
    Subject  :    out List
    Bytes    : in     Ada.Streams.Stream_Element_Array) ;

However, you can kind of roll-your-own from what you've already provided.
I'd see it as convenience and simplicity to have the above.

MDC
--
Marin David Condic
Senior Software Engineer
Pace Micro Technology Americas    www.pacemicro.com
Enabling the digital revolution
e-Mail:    marin.condic@pacemicro.com
Web:      http://www.mcondic.com/


"Ted Dennison" <dennison@telepath.com> wrote in message
news:3BE301D1.4010106@telepath.com...
> I have a new version of the strawman up at my website at
> http://www.telepath.com/dennison/Ted/Containers-Lists-Unbounded.ads.html
> . This version has the cascading style sheet too, so hopefully nearly
> everyone should be able to read it.






^ permalink raw reply	[relevance 2%]

* Re: How Can I Create A Class Dynamically
  2001-10-04  8:55  0%     ` Lutz Donnerhacke
@ 2001-10-04 17:06  0%       ` R. Tim Coslet
  0 siblings, 0 replies; 200+ results
From: R. Tim Coslet @ 2001-10-04 17:06 UTC (permalink / raw)


lutz@iks-jena.de (Lutz Donnerhacke) wrote in message news:<slrn9ro8vr.4a.lutz@taranis.iks-jena.de>...
> * R. Tim Coslet wrote:
> >lutz@iks-jena.de (Lutz Donnerhacke) wrote in message news:<slrn9rgoo2.k8.lutz@taranis.iks-jena.de>...
> >
> >Have you looked at the package Ada.Streams.Stream_IO ?
> >
> >This package was designed specifically to allow input/output of tagged
> >types (the file is NOT a text file however).
> 
> I wonder if Stream_IO is able to read instances of derivated types unknown
> at the compile time of the programm. I'd look at the Objective-* Code.

No, all types must have been defined at compile time or there is no
internal representation for the Stream representation and Stream_IO
will raise Constraint_Error.

If the types were not defined at compile time and Stream_IO accepted
them, the program would not know how to work with the objects... all
operators of a 'Class are defined at compile time.



^ permalink raw reply	[relevance 0%]

* Re: How Can I Create A Class Dynamically
  2001-10-02 23:13  2%   ` R. Tim Coslet
@ 2001-10-04  8:55  0%     ` Lutz Donnerhacke
  2001-10-04 17:06  0%       ` R. Tim Coslet
  0 siblings, 1 reply; 200+ results
From: Lutz Donnerhacke @ 2001-10-04  8:55 UTC (permalink / raw)


* R. Tim Coslet wrote:
>lutz@iks-jena.de (Lutz Donnerhacke) wrote in message news:<slrn9rgoo2.k8.lutz@taranis.iks-jena.de>...
>> * Anthony E. Glover wrote:
>> >I have a class hierarchy defined and I would like to be able to read a
>> >string and then dynamically creating a pointer to an object of the type
>> >specified by the string. Similar I think to class loading and class
>> >factories in Java. Can this be done in Ada95. If so, how. I have looked at
>> >the Ada.Tags packages and this looks like it might be helpfull, but I'm not
>> >quite sure how to make use of it. I would basically like to be able to avoid
>> >having to specify a case statement or if block when initially creating my
>> >objects.
>> 
>> IMHO this is not possible, due to missing typeness.
>
>Have you looked at the package Ada.Streams.Stream_IO ?
>
>This package was designed specifically to allow input/output of tagged
>types (the file is NOT a text file however).

I wonder if Stream_IO is able to read instances of derivated types unknown
at the compile time of the programm. I'd look at the Objective-* Code.



^ permalink raw reply	[relevance 0%]

* Re: How Can I Create A Class Dynamically
  @ 2001-10-02 23:13  2%   ` R. Tim Coslet
  2001-10-04  8:55  0%     ` Lutz Donnerhacke
  0 siblings, 1 reply; 200+ results
From: R. Tim Coslet @ 2001-10-02 23:13 UTC (permalink / raw)


lutz@iks-jena.de (Lutz Donnerhacke) wrote in message news:<slrn9rgoo2.k8.lutz@taranis.iks-jena.de>...
> * Anthony E. Glover wrote:
> >I have a class hierarchy defined and I would like to be able to read a
> >string and then dynamically creating a pointer to an object of the type
> >specified by the string. Similar I think to class loading and class
> >factories in Java. Can this be done in Ada95. If so, how. I have looked at
> >the Ada.Tags packages and this looks like it might be helpfull, but I'm not
> >quite sure how to make use of it. I would basically like to be able to avoid
> >having to specify a case statement or if block when initially creating my
> >objects.
> 
> IMHO this is not possible, due to missing typeness.

Have you looked at the package Ada.Streams.Stream_IO ?

This package was designed specifically to allow input/output of tagged
types (the file is NOT a text file however).

Even if Stream_IO isn't exactly what you are looking for you might
find some clues here as to how to do what you need.



^ permalink raw reply	[relevance 2%]

* Re: Unix text handling on stdin
    2001-08-24 23:44  2% ` sk
@ 2001-08-25  2:56  2% ` sk
  1 sibling, 0 replies; 200+ results
From: sk @ 2001-08-25  2:56 UTC (permalink / raw)
  To: comp.lang.ada

Hi again,

I wrote:
>I fully intended to look up the issue in both the LRM and
>Ada Issues to see if the compiler was behaving according to
>spec, but once I found a work-around, I never got round
>to checking about the legitimacy of this TIO behaviour.

Firstly, I should have said text-io behaving according to spec,
and not "the compiler" ... and then I got around to actually
reading up on the issue.


From the Ada95 Reference Manual (Electronic, provided with GNAT 
.../gnat-3.13p-unx-docs/html/arm95.html#SEC247)

:Text File Management
:
:...
:
:2.For the procedure Close: If the file has the current mode 
:Out_File or Append_File, has the effect of calling New_Page,
:unless the current page is already terminated; then outputs
:a file terminator. 
:
:...
:

So, the behaviour of adding a file terminating byte in 
closing a file from Text_IO agrees with the ARM.

It also appears that Interfaces.C_Streams and Ada.Text_Io.C_Streams
are provided by GNAT. The packages do not seem to be documented
in the above mentioned electronic ARM; they are, however,
documented in the GNAT RM
(.../gnat-3.13p-unx-docs/html/gnat_rm.html#SEC42).

sknipe@ktc.com

PS The example makes no use of Ada.Streams and Ada.Streams.Stream_Io;
as I mentioned, it was a QUAD and therefore subject to not editing
out the unecessary items from a cut and paste job.



^ permalink raw reply	[relevance 2%]

* Re: Unix text handling on stdin
  @ 2001-08-24 23:44  2% ` sk
  2001-08-25  2:56  2% ` sk
  1 sibling, 0 replies; 200+ results
From: sk @ 2001-08-24 23:44 UTC (permalink / raw)
  To: comp.lang.ada

[-- Attachment #1: Type: text/plain, Size: 1048 bytes --]

Hi, 

I tried the ICFP thing for S&G's (didn't, and didn't intend to, 
really enter) and ran into the same problem ...

So, my solution involved

Ada.Text_Io;
Ada.Text_Io.C_Streams;
Interfaces.C_Streams;

and here is a distilled way to take std in and copy it to 
stdout without TIO adding extra Line feeds when closing 
the file etc.

I fully intended to look up the issue in both the LRM and
Ada Issues to see if the compiler was behaving according to
spec, but once I found a work-around, I never got round
to checking about the legitimacy of this TIO behaviour.

The output of this procedure will be of exactly the same
size as the input ... unlike when exclusively using TIO
which always added an extra byte or two when closing.

sknipe@ktc.com

PS. Please note that this is a QAD[1] and not very careful such
that exceptions can and will be raised by going out of range

[1] Quick and Dirty :-)

PPS. Text attachment, sorry, to preserve formatting ...

PPPS. Linux, GNAT 3.13p

----------------------------------------------------------------

[-- Attachment #2: standard_io_play.adb --]
[-- Type: text/plain, Size: 2945 bytes --]

with Interfaces.C_Streams;

with Ada.Streams;
with Ada.Streams.Stream_Io;

with Ada.Text_Io;
with Ada.Text_Io.C_Streams;

procedure Standard_IO_Play is

	package ICS				renames Interfaces.C_Streams;
	
	package AS				renames Ada.Streams;
	package ASSIO			renames Ada.Streams.Stream_Io;

	package TIO				renames Ada.Text_Io;
	package TIOCS			renames Ada.Text_Io.C_Streams;
	
	function Is_File_A_Tty (
		File : Ada.Text_Io.File_Type
	) return Boolean is
	begin
		return (
			Interfaces.C_Streams.Isatty (
				Interfaces.C_Streams.FileNo (
					Ada.Text_Io.C_Streams.C_Stream (File)
				)
			) > 0
		);
	end Is_File_A_Tty;

	Buffer_Size	: constant := 10240; 	-- 10k buffer size


	Buffer	: String (1 .. Buffer_Size) := (Others => ' ');
	Last	: Natural := Buffer'Last;

	Buffer_Address	: constant ICS.Voids := Buffer(Buffer'First)'Address;
	Element_Size	: constant := Character'Size / 8;

	Bytes_Read		: ICS.Size_t := 0;
	Bytes_Written   : ICS.Size_t := 0;

	Flush_Result	: Integer;

begin
	-- First, check whether Std_In is attached to a tty or is 
	-- something else.
	-- If stdin is a tty, then expecting ketboard user input
	-- else (not a tty) assuming that the OS is piping a file 
	--     to this procedure
	-- (Remember this is just an example and that it is prabably
	--  a bad assumption and oversimplification). 
	--

	if Is_File_A_Tty (TIO.Current_Input) then
	
	
		TIO.Put_Line (
			File => TIO.Standard_Error,
			Item => "Trying to show piping. So please pipe into this procedure"
		);
		TIO.Put_Line (
			File => TIO.Standard_Error,
			Item => "ie # ""cat test-file | ./standard_io_play > result-file"""
		);
	
	else 
	
		Std_In_Read : loop
		
			exit Std_In_Read when TIO.End_Of_File (TIO.Current_Input);
			
			-- Read using ICS ...

			Bytes_Read := ICS.Fread (
				Buffer	=> Buffer_Address,
				Size	=> Element_Size,
				Count	=> ICS.Size_t (Buffer'Length),
				Stream	=> TIOCS.C_Stream (TIO.Current_Input)
			);
			
			-- Do your thing to the buffer ... (Note the possibility of
			-- incompatible ranges for Natural (Bytes_Read) and subsequent
			-- buffer overflows).
			
			Processing : for Char in Buffer'First .. Natural (Bytes_Read) loop

				if Buffer(Char) = ASCII.Lf then

					TIO.Put_Line (
						File	=> TIO.Standard_Error,
						Item    => "Found LF"
					);
					
				elsif Buffer(Char) = ASCII.Cr then

					TIO.Put_Line (
						File	=> TIO.Standard_Error,
						Item    => "Found CR"
					);
					
				elsif Buffer(Char) = ASCII.Ht then

					TIO.Put_Line (
						File	=> TIO.Standard_Error,
						Item    => "Found TAB"
					);
				
				end if;

			end loop Processing;
			
			-- Write using ICS ...

			Bytes_Written := ICS.Fwrite (
				Buffer	=> Buffer_Address,
				Size	=> Element_Size,
				Count	=> ICS.Size_t (Bytes_Read),
				Stream	=> TIOCS.C_Stream (TIO.Current_Output)
			);

		end loop Std_In_Read;

		Flush_Result := ICS.Fflush (TIOCS.C_Stream (TIO.Current_Output));

	end if;


end Standard_IO_Play;


^ permalink raw reply	[relevance 2%]

* Re: Where's the goodies?
  @ 2001-08-20 20:50  2% ` Ted Dennison
  0 siblings, 0 replies; 200+ results
From: Ted Dennison @ 2001-08-20 20:50 UTC (permalink / raw)


In article <3B815D9C.9C22AA7A@san.rr.com>, Darren New says...
>
>and such. What I'll definitely need is byte-oriented I/O to files and
>sockets (i.e., raw binary files), as well as access to directories and

I should point out that this can be done portably with the routines in
Ada.Streams.Stream_IO and Ada.Streams.Write and Ada.Streams.Read.

>My question is, where's the goodies? These things have to be out there,
>but there's no documentation about them in the GNAT distribution that

If you are on Windows and installed to the default place, you have a full Win32
binding in c:/GNAT/Bindings/Win32Ada . Of course you can only legally use it if
you have a licensed copy of the C header files (eg: VC++). The rest of the
included stuff is in c:/GNAT/lib/gcc-lib/pentium-mingw32msv/2.8.1/adainclude (I
know what you are saying, "Why didn't I think to look there?" :-)  ). The file
names are kinda cryptic. Look particularly at all the g-* files, as those are
the "Gnat" hierarchy. "g-regexp" for instance is the regular-expression matching
stuff.

As for stuff that *doesn't* come with Gnat, check out my homepage for a small
selection that I use (if you find dead links, tell me). Also check out
http://www.adapower.com/reuse/index.html

---
T.E.D.    homepage   - http://www.telepath.com/dennison/Ted/TED.html
          home email - mailto:dennison@telepath.com



^ permalink raw reply	[relevance 2%]

* Re: implementation question about writing and reading from files
  2001-08-10 14:49  2%     ` Ted Dennison
@ 2001-08-10 15:44  0%       ` Warren W. Gay VE3WWG
  0 siblings, 0 replies; 200+ results
From: Warren W. Gay VE3WWG @ 2001-08-10 15:44 UTC (permalink / raw)


Ted Dennison wrote:
> In article <9kv5rs$6hosn$2@ID-102190.news.dfncis.de>, Francis Crick says...
> >And also, if I want to use a stream for keeping data in memory, how do i
> >that?  How do i instantiate a stream that I can just write to and read from
> >at my leisure?
> 
> The only language-defined streams are in Ada.Streams.Stream_IO,
> Ada.Text_IO.Text_Streams, and Ada.Wide_Text_IO.Text_Streams. I believe they all
> deal with files. If you want to use one to make yourself a buffer, you will have
> to code it yourself by deriving it from Ada.Streams.Root_Stream_Type and
> overriding "Read" and "Write".

If you want a number of examples of streams code, download the AdaVox software
from: http://members.home.net/ve3wwg

I am currently re-vamping AdaVox, because there are a number of design problems
in it, but in the originally released code (see above), you will find
some code that implements a stream buffer. Look for file wc-streams-buffer.ads.

I am sure you can improve upon it, but it will get you started at least.

> 
> >               Also, the data I'm moving is large, and chances are I won't
> >be using it for much else other than writing back to other file streams, so
> >how can i make the reading and writing as fast as possible?  Could I make it
> >read a whole mb in one go as a single unit?
> 
> The easiest way to do that is to unchecked_conversion your data (or better yet,
> a pointer to it) into a Ada.Streams.Stream_Element_Array, then call
> Ada.Streams.Write directly. If you just use the stream attributes, it will
> perform one write for each element, which I've found to be significantly slower
> (even when the target is a memory-based stream).

I think the GNAT implementation is built upon the stdio (C) package, ultimately.
One way to improve performance some, is to increase the buffer size of the 
underlying "file". You'll need to look at the GNAT User Guide to find out how.
You will need to open a C file, and then turn it into an Ada stream.
Maybe someone else can volunteer the details here (I'm too pressed for
time to look it up).

This won't compensate for the procedure(attribute) calls (that Ted referred to), 
but it will make each I/O a larger one.

> A good Ada book should go over the basics of this. Stream use is a complicated
> enough topic that you really ought to have such a resource to learn the basics
> from.

Otherwise, be prepared to look at the streams specs a lot (as I did).
-- 
Warren W. Gay VE3WWG
http://members.home.net/ve3wwg



^ permalink raw reply	[relevance 0%]

* Re: implementation question about writing and reading from files
  2001-08-09 23:19  0%   ` Francis Crick
  2001-08-10  0:55  3%     ` tmoran
@ 2001-08-10 14:49  2%     ` Ted Dennison
  2001-08-10 15:44  0%       ` Warren W. Gay VE3WWG
  1 sibling, 1 reply; 200+ results
From: Ted Dennison @ 2001-08-10 14:49 UTC (permalink / raw)


In article <9kv5rs$6hosn$2@ID-102190.news.dfncis.de>, Francis Crick says...
>And also, if I want to use a stream for keeping data in memory, how do i
>that?  How do i instantiate a stream that I can just write to and read from
>at my leisure? 

The only language-defined streams are in Ada.Streams.Stream_IO,
Ada.Text_IO.Text_Streams, and Ada.Wide_Text_IO.Text_Streams. I believe they all
deal with files. If you want to use one to make yourself a buffer, you will have
to code it yourself by deriving it from Ada.Streams.Root_Stream_Type and
overriding "Read" and "Write". 

>               Also, the data I'm moving is large, and chances are I won't
>be using it for much else other than writing back to other file streams, so
>how can i make the reading and writing as fast as possible?  Could I make it
>read a whole mb in one go as a single unit?

The easiest way to do that is to unchecked_conversion your data (or better yet,
a pointer to it) into a Ada.Streams.Stream_Element_Array, then call
Ada.Streams.Write directly. If you just use the stream attributes, it will
perform one write for each element, which I've found to be significantly slower
(even when the target is a memory-based stream).

A good Ada book should go over the basics of this. Stream use is a complicated
enough topic that you really ought to have such a resource to learn the basics
from.

---
T.E.D.    homepage   - http://www.telepath.com/dennison/Ted/TED.html
          home email - mailto:dennison@telepath.com



^ permalink raw reply	[relevance 2%]

* Re: implementation question about writing and reading from files
  2001-08-09 23:19  0%   ` Francis Crick
@ 2001-08-10  0:55  3%     ` tmoran
  2001-08-10 14:49  2%     ` Ted Dennison
  1 sibling, 0 replies; 200+ results
From: tmoran @ 2001-08-10  0:55 UTC (permalink / raw)


>the parameters mean...obviously File_Type is the file i'm getting, but what
>about the Item and Last parameters?  Is Stream_Element a generic type I have
>to declare, and if so, how and where do I do that?  If not, how can I ensure
>I'm getting the amount of data out of the file that I want on any platform?
>
>The From param in Read - what does this represent exactly?  from byte #?
>from Stream_Element # in the stream?
  You need a book, or look at www.adapower.com for the Ada 95 Reference
Manual (ARM).  A.12.1(31) says "The position of the first element in the
file is 1."  The Ada.Streams.Stream_IO Read and Write operate with
Stream_Element_Array's, which are defined in Ada.Streams, where ARM
13.13.1(4) says
  type Stream_Element is mod (implementation defined);
Probably a Stream_Element is a single byte, but there are weird systems
where it might be a 20 bit word or something.  Check your compiler's docs.

>How do i instantiate a stream that I can just write to and read from
>at my leisure?
  You can certainly do Ada.Streams.Stream_IO Read and Write at your
leisure.  There's nothing to instantiate, just use it.  It's even
simpler than Text/Sequential/Direct_IO.

>Also, the data I'm moving is large, and chances are I won't
>be using it for much else other than writing back to other file streams, so
>how can i make the reading and writing as fast as possible?  Could I make it
>read a whole mb in one go as a single unit?
  Ada.Streams.Stream_IO.Read/Write ought to be fast.  They don't do
any formatting or buffering or anything, just straightforward byte
(actually Stream_Element_Array) IO.  If you Declare
  Glob : Ada.Streams.Stream_Element_Array(1 .. 1_000_000);
you can read or write the whole thing in one call.

>And also, if I want to use a stream for keeping data in memory, how do i
>that?
  Not with Ada.Streams.Stream_IO.  There is something else entirely,
Ada.Streams, that handles automatically reading and writing everything
from a boolean to an array of tagged records.  It doesn't actually do
any IO - it just handles converting things to and from byte streams
(well, actually Stream_Element_Arrays) and calls your routine to do
the actual IO.  If you want to move things in memory, have your
routine do that, and not do any IO.

What is the level of abstraction here?  If you aren't looking at the
contents of the data, but just shoving it around, use
Ada.Streams.Stream_IO.  If you are looking at is as structured
information that you want to pay attention to, then use Ada.Streams
as well, or even use Ada.Direct_IO if it's just a series of fixed
size records.



^ permalink raw reply	[relevance 3%]

* Re: implementation question about writing and reading from files
  2001-08-05 22:43  2% ` tmoran
@ 2001-08-09 23:19  0%   ` Francis Crick
  2001-08-10  0:55  3%     ` tmoran
  2001-08-10 14:49  2%     ` Ted Dennison
  0 siblings, 2 replies; 200+ results
From: Francis Crick @ 2001-08-09 23:19 UTC (permalink / raw)


I'm still really confused about these calls...anyone willing to offer me
some extra help?

I've been playing around with these calls but i really don't understand what
the parameters mean...obviously File_Type is the file i'm getting, but what
about the Item and Last parameters?  Is Stream_Element a generic type I have
to declare, and if so, how and where do I do that?  If not, how can I ensure
I'm getting the ammount of data out of the file that I want on any platform?

The From param in Read - what does this represent exactly?  from byte #?
from Stream_Element # in the stream?

And also, if I want to use a stream for keeping data in memory, how do i
that?  How do i instantiate a stream that I can just write to and read from
at my leisure?  Also, the data I'm moving is large, and chances are I won't
be using it for much else other than writing back to other file streams, so
how can i make the reading and writing as fast as possible?  Could I make it
read a whole mb in one go as a single unit?

Sorry most of these are no-brainers...I'm still a total Ada newbie and I
haven't really got a grasp of the way things work yet...

TIA!

Francis Crick

<tmoran@acm.org> wrote in message
news:j_jb7.33402$Kd7.20784576@news1.rdc1.sfba.home.com...
>   I'd suggest Ada.Streams.Stream_IO
>
> > read a chunk of any size from any part of a file and write it into
memory
> > and pass back the pointer.
>     procedure Read (File : in     File_Type;
>                     Item :    out Stream_Element_Array;
>                     Last :    out Stream_Element_Offset;
>                     From : in     Positive_Count);
>
> > write a chunk of any size into any part of any file.
>   assuming "any file" does not include, for instance, printer output,
>     procedure Write(File : in     File_Type;
>                     Item : in     Stream_Element_Array;
>                     From : in     Positive_Count);









^ permalink raw reply	[relevance 0%]

* Re: implementation question about writing and reading from files
  @ 2001-08-05 22:43  2% ` tmoran
  2001-08-09 23:19  0%   ` Francis Crick
  0 siblings, 1 reply; 200+ results
From: tmoran @ 2001-08-05 22:43 UTC (permalink / raw)


  I'd suggest Ada.Streams.Stream_IO

> read a chunk of any size from any part of a file and write it into memory
> and pass back the pointer.
    procedure Read (File : in     File_Type;
                    Item :    out Stream_Element_Array;
                    Last :    out Stream_Element_Offset;
                    From : in     Positive_Count);

> write a chunk of any size into any part of any file.
  assuming "any file" does not include, for instance, printer output,
    procedure Write(File : in     File_Type;
                    Item : in     Stream_Element_Array;
                    From : in     Positive_Count);



^ permalink raw reply	[relevance 2%]

Results 1-200 of ~300   | reverse | options above
-- pct% links below jump to the message on this page, permalinks otherwise --
2001-08-05 22:18     implementation question about writing and reading from files Francis Crick
2001-08-05 22:43  2% ` tmoran
2001-08-09 23:19  0%   ` Francis Crick
2001-08-10  0:55  3%     ` tmoran
2001-08-10 14:49  2%     ` Ted Dennison
2001-08-10 15:44  0%       ` Warren W. Gay VE3WWG
2001-08-20 18:57     Where's the goodies? Darren New
2001-08-20 20:50  2% ` Ted Dennison
2001-08-24 21:36     Unix text handling on stdin David Starner
2001-08-24 23:44  2% ` sk
2001-08-25  2:56  2% ` sk
2001-09-24 16:32     How Can I Create A Class Dynamically Anthony E. Glover
2001-10-01 12:35     ` Lutz Donnerhacke
2001-10-02 23:13  2%   ` R. Tim Coslet
2001-10-04  8:55  0%     ` Lutz Donnerhacke
2001-10-04 17:06  0%       ` R. Tim Coslet
2001-11-02 20:29     List container strawman 1.1 Ted Dennison
2001-11-05 16:01  2% ` Marin David Condic
2001-11-05 20:06  2%   ` Ted Dennison
2001-11-05 20:45  0%     ` Marin David Condic
2001-11-05 22:37  0%   ` Nick Roberts
2001-11-06 12:38     ` Roy Bell
2001-11-08 10:56       ` Ehud Lamm
2001-11-08 18:08         ` Roy Bell
2001-11-09 15:55  2%       ` Ted Dennison
2001-11-25 22:42     Text_IO.End_Of_File Problem Hambut
2001-11-26  2:35     ` Nick Roberts
2001-11-26 12:13       ` Hambut
2001-11-26 18:00  1%     ` Nick Roberts
2001-11-27  9:51  0%       ` Hambut
2002-01-09  0:04     Ada way to read/write to character file Nick Roberts
2002-01-09  2:12     ` tmoran
2002-01-09 12:11  1%   ` Nick Roberts
2002-01-11 13:48     How to avoid unreferenced objects (mutexes etc) Dmitry A. Kazakov
2002-01-12  1:11     ` Nick Roberts
2002-01-14  9:42       ` Dmitry A. Kazakov
2002-01-15 18:59  2%     ` Nick Roberts
2002-01-23  4:10  3% Reading from a saved stream Paul Pukite
2002-01-24  6:03  0% ` Greg Bek
2002-02-16  9:40     Adasockets storage problem Nazgul
2002-02-17  7:09  2% ` Simon Wright
2002-02-21 12:37  3% How to speed up stream & record handling? Karl Ran
2002-02-24  3:23  3% ` Nick Roberts
2002-02-22 13:31     Karl Ran
2002-02-22 20:25  3% ` tmoran
2002-02-25 17:08     reading from a file Deepie
2002-02-25 17:23     ` John McCabe
2002-02-25 20:30       ` Deepie
2002-02-25 20:46  2%     ` sk
2002-03-24 23:18  3% Read booleans from streams Erik Sigra
2002-03-25  3:57  0% ` Eric G. Miller
2002-03-25 18:53  3% Another problem with stream reading Erik Sigra
2002-03-26 17:54  0% ` Warren W. Gay VE3WWG
2002-03-27 15:53  0%   ` Erik Sigra
2002-04-10 16:33     Development process in the Ada community Michael Erdmann
2002-04-19 14:23     ` Grace and Maps (was Re: Development process in the Ada community) Marin David Condic
2002-04-20 19:49       ` Ted Dennison
2002-04-21  1:33         ` Ted Dennison
2002-04-23 17:50           ` Warren W. Gay VE3WWG
2002-04-23 18:59             ` Stephen Leake
2002-04-23 19:13               ` Darren New
2002-04-23 19:26                 ` Stephen Leake
2002-04-23 19:44                   ` Darren New
2002-04-24 16:49                     ` Stephen Leake
2002-04-24 17:10                       ` Marin David Condic
     [not found]                         ` <aa8ssi$qjr$1 <3CCD6197.9070905@mail.com>
2002-04-30  4:49                           ` Simon Wright
2002-04-30 14:05                             ` Ted Dennison
2002-04-30 14:32                               ` Marin David Condic
2002-05-02 15:52  2%                             ` Ted Dennison
2002-06-10 19:38     Behavior of Stream Attributes On Access Types Marin David Condic
2002-06-12  3:44  3% ` David C. Hoos, Sr.
2002-07-30  6:32     FAQ and string functions Oleg Goodyckov
2002-07-30 13:48     ` Ted Dennison
2002-07-31  7:46       ` Oleg Goodyckov
2002-08-01 14:29  1%     ` Ted Dennison
2002-08-14 19:34     Fill string with multiple lines from standard_input Vincent Smeets
2002-08-14 20:37     ` Stephen Leake
2002-08-15 17:57       ` Vincent Smeets
2002-08-15 20:47         ` Stephen Leake
2002-08-19 19:39           ` Vincent Smeets
2002-08-20 15:01             ` Stephen Leake
2002-08-20 18:26  3%           ` Vincent Smeets
2002-08-20 19:46  0%             ` tmoran
2002-08-21 12:50  0%             ` Jean-Pierre Rosen
2002-08-21 19:19  0%             ` Randy Brukardt
2002-08-27 12:29  2% Bug in GNAT.Traceback.Symbolic? Joachim Schröer
2002-09-12  2:35     Thoughts on the recent ICFP contest Ted Dennison
2002-09-12  3:11     ` tmoran
2002-09-12 14:23       ` Wes Groleau
2002-09-12 16:43  2%     ` Ted Dennison
2002-09-12 16:53         ` David C. Hoos
2002-09-16 20:41           ` Wes Groleau
2002-09-17  3:21  2%         ` Ted Dennison
2002-10-14  7:39  3% Streams and files Sim Con
2002-10-14  8:30  0% Grein, Christoph
2003-02-11 18:34     Random Access in Ada.Text_IO files Micha� Morawski
2003-02-11 18:58  2% ` Stephen Leake
2003-02-24 14:19     Help needed; Saving access types with sequential_io? khendon
2003-02-24 17:58  2% ` Rodrigo García
2003-02-28 12:08     Getting a symbol table from Gnat 3.15p on Windows Marin David Condic
2003-02-28 20:24  3% ` tmoran
2003-03-01 18:25  0%   ` John R. Strohm
2003-04-03  7:28  3% Access to T'Class vs T'Class as parameter to subprogram Frank
2003-04-07 12:47     Persistence of limited tagged types Jano
2003-04-07 14:47     ` Nick Roberts
2003-04-09 10:05  2%   ` Nick Roberts
2003-05-21  0:07     'Write attribute vs Write procedure Jano
2003-05-21  0:42     ` tmoran
2003-05-23  6:09       ` Craig Carey
2003-05-23 19:55         ` Simon Wright
2003-05-23 20:48           ` AI-248 and counting the elements in an external file Larry Kilgallen
2003-05-23 21:12             ` Stephen Leake
2003-05-23 21:45               ` Randy Brukardt
2003-05-24  1:45                 ` Larry Kilgallen
2003-05-24 22:00                   ` Robert I. Eachus
2003-05-25  3:54                     ` Larry Kilgallen
2003-05-27 20:19                       ` Randy Brukardt
2003-05-27 20:57                         ` Larry Kilgallen
2003-05-28 18:26  1%                       ` Randy Brukardt
2003-07-01 19:04  2% Gnat.Sockets.Stream memory "leak" Jano
2003-07-11 12:05  1% Computer Language Shootout Craig Carey
2003-07-15 20:13  2% Ada.Streams.Stream_IO.File_Type tmoran
2003-07-17 15:10  4% ` Ada.Streams.Stream_IO.File_Type Craig Carey
2003-07-17 16:42  2%   ` Ada.Streams.Stream_IO.File_Type Nick Roberts
2003-07-18 17:34  2%     ` Ada.Streams.Stream_IO.File_Type Matthew Heaney
2003-07-18 18:25  5%       ` Ada.Streams.Stream_IO.File_Type David C. Hoos
2003-07-17 16:01  5% ` Ada.Streams.Stream_IO.File_Type Nick Roberts
2003-07-20 11:27  2%   ` Ada.Streams.Stream_IO.File_Type Mário Amado Alves
2003-07-20 14:25  2%     ` Ada.Streams.Stream_IO.File_Type Robert I. Eachus
2003-07-21  4:03  2%       ` Ada.Streams.Stream_IO.File_Type Nick Roberts
2003-07-21  9:47  2%         ` Ada.Streams.Stream_IO.File_Type Robert I. Eachus
2003-07-18  7:46  2% ` Ada.Streams.Stream_IO.File_Type Dmitry A. Kazakov
2003-11-21  6:57     ftp client package Volkert
2003-11-21  8:18  2% ` tmoran
2004-03-26 17:30  2% Stream_Element_Array 2 String Shaddow
2004-03-26 18:04  2% ` Marius Amado Alves
2004-03-27  8:24  0%   ` Simon Wright
2004-07-15 17:27     reading a text file into a string zork
2004-07-15 17:59  2% ` Marius Amado Alves
2004-07-15 19:18  0%   ` Nick Roberts
2004-10-04 19:16     excel files Alexandre Devaure
2004-10-04 19:42     ` stephane richard
2004-10-05  1:20  2%   ` Stephen Leake
2004-11-16  4:16  5% Ada.Streams.Stream_IO.Stream_Access Alex
2004-11-16  8:06  2% ` Ada.Streams.Stream_IO.Stream_Access Marius Amado Alves
2004-11-16  8:28  2% ` Ada.Streams.Stream_IO.Stream_Access Martin Krischik
2004-11-16 18:19  2%   ` Ada.Streams.Stream_IO.Stream_Access Alex
2004-11-16 18:52  2%     ` Ada.Streams.Stream_IO.Stream_Access tmoran
2004-11-17  9:31  2%       ` Ada.Streams.Stream_IO.Stream_Access Martin Krischik
2004-12-15  7:43     Ada streams Daniel Vencler
2004-12-15 17:26  2% ` Nick Roberts
2004-12-15 19:35  2%   ` tmoran
2005-03-01  9:30     Advanced file manipulation (multiple question) Steph-ADA
2005-03-01 17:49  1% ` Jeffrey Carter
2005-03-19 16:22     Ada bench Pascal Obry
2005-03-19 16:55     ` Dr. Adrian Wrigley
2005-03-19 21:32       ` Michael Bode
2005-03-20  9:20         ` Pascal Obry
2005-03-21 23:27           ` Georg Bauhaus
2005-03-22  1:16             ` Ada bench : count words Marius Amado Alves
2005-03-22 10:59               ` Dmitry A. Kazakov
2005-03-22 12:22  2%             ` Jeff C
2005-03-22 19:49  2%           ` tmoran
2005-03-22 21:51  0%             ` Dmitry A. Kazakov
2005-03-22 22:33  0%             ` Marius Amado Alves
     [not found]                 ` <00b362390273e6c04844dd4ff1885ee0@netcabo.pt>
2005-03-23 15:09  2%               ` Marius Amado Alves
2005-03-30 16:08  0%                 ` Andre
2005-04-07 20:59       ` Ada bench David Sauvage
2005-04-08 17:11         ` Pascal Obry
2005-04-18 19:14  2%       ` David Sauvage
2005-04-19 16:43  0%         ` Matthew Heaney
2005-04-19 23:22  2%           ` David Sauvage
2005-04-20  0:49  0%             ` Matthew Heaney
2005-04-20 21:24  2%               ` David Sauvage
2005-04-20  9:41  0%             ` Pascal Obry
2005-03-23 19:00     Ada bench : count words tmoran
2005-03-23 19:54     ` Tapio Kelloniemi
2005-03-23 20:39  2%   ` Ada bench : word frequency Marius Amado Alves
2005-03-23 21:26         ` Isaac Gouy
2005-03-24  1:24  2%       ` Marius Amado Alves
2005-03-23 19:30     Ada bench : count words tmoran
2005-03-23 21:38  2% ` tmoran
2005-03-26 13:53     Gnat 3.15p & Windows & Hyperthreading Q Marin David Condic
2005-03-26 18:36  2% ` tmoran
2005-03-28 13:16  0%   ` Marin David Condic
2005-04-25 21:30     [Shootout] Spellcheck.adb albert.bachmann
2005-04-26 19:36  1% ` David Sauvage
2005-05-09 10:11     Sending Variable Length Messages with GNAT.Sockets markp
2005-05-09 10:39     ` Adrien Plisson
2005-05-09 11:19       ` markp
2005-05-09 14:30         ` John B. Matthews
2005-05-09 14:51           ` markp
2005-05-09 18:49  2%         ` Adrien Plisson
2006-04-22  1:33  5% Q: Index value in case of Ada.Streams.Stream_IO.End_Error Gautier
2006-04-24  8:11  2% ` Jean-Pierre Rosen
2006-04-24 14:33  5%   ` Gautier
2006-04-24 16:05  2%     ` Jean-Pierre Rosen
2006-04-24 17:44  2%       ` Gautier
2006-06-20 16:56  1% Compiler Bug or what I'm doing wrong? M E Leypold
2006-06-23  9:55  2% ` A smaller self contained test case. Was: " M E Leypold
2006-06-23 11:04  2%   ` And a Workaround: Was: A smaller test case / Compiler Bug M E Leypold
2006-06-24 11:46       ` A smaller self contained test case. Was: Compiler Bug or what I'm doing wrong? Dmitry A. Kazakov
2006-06-24 12:27         ` M E Leypold
2006-06-24 12:52           ` Dmitry A. Kazakov
2006-06-24 13:53             ` M E Leypold
2006-06-24 19:58  2%           ` Dmitry A. Kazakov
2007-01-30 15:51     Reading Float Data from a binary file into ada frikk
2007-01-30 19:31  2% ` Niklas Holsti
2007-02-14 20:58  3% My bug or compiler bug? Anh Vo
2007-03-09 22:43     Design help Carroll, Andrew
2007-03-09 23:07  2% ` Simon Wright
2007-03-10 13:38  2% ` Ludovic Brenta
2007-04-02  6:13  1% STORAGE_ERROR : EXCEPTION_STACK_OVERFLOW andrew.carroll
2007-04-02 10:10     ` Stephen Leake
2007-04-02 14:11  1%   ` andrew.carroll
2007-04-02 22:05  1% ` andrew.carroll
2007-04-12 13:48  2% ` andrew.carroll
2007-08-02  7:43  1% Mixing reading and writing to a text file msimonides
2007-08-03  1:26  2% ` Randy Brukardt
2007-08-06  7:35  2%   ` msimonides
2008-08-05  2:16  2% Controlling endian-ness? Peter C. Chapin
2008-08-05  3:10  0% ` Steve
2008-08-05 14:59  0% ` anon
2008-08-05 22:14       ` Peter C. Chapin
2008-08-06 17:07  3%     ` Controlling endian-ness? (Example: Attribute Overriding) anon
2009-01-01 11:16     Ada.Directories problems, a summary Dmitry A. Kazakov
2009-01-01 13:47     ` Ivan Levashew
2009-01-01 14:15  1%   ` Dmitry A. Kazakov
2009-01-02 14:22  0%     ` Ivan Levashew
2009-01-02 14:49  0%       ` Dmitry A. Kazakov
2009-04-03 12:01     Load an object from a file Olivier Scalbert
2009-04-03 13:37     ` Ludovic Brenta
2009-04-09 20:32       ` Olivier Scalbert
2009-04-09 21:22  3%     ` Ludovic Brenta
2009-07-18 14:19     Alternatives to C: ObjectPascal, Eiffel, Ada or Modula-3? Andrea Taverna
2009-07-20 12:15     ` Nicholas Paul Collin Gloucester
2009-07-20 18:33       ` Cesar Rabak
2009-07-20 19:44         ` Nicholas Paul Collin Gloucester
2009-07-20 20:14           ` Cesar Rabak
2009-07-20 22:22             ` Ludovic Brenta
2009-07-21  1:33               ` Cesar Rabak
2009-07-21  7:54  3%             ` Ludovic Brenta
2009-08-01 12:21     Ada Shootout program for K-Nucleotide (patches) Georg Bauhaus
2009-08-01 15:21     ` Ludovic Brenta
2009-08-03  8:56       ` Jacob Sparre Andersen
2009-08-03 11:43         ` Georg Bauhaus
2009-08-03 12:36           ` Jacob Sparre Andersen
2009-08-03 18:31             ` Isaac Gouy
2009-08-03 20:29               ` Robert A Duff
2009-08-04 15:43                 ` Isaac Gouy
2009-08-04 16:06                   ` Isaac Gouy
2009-08-04 17:08                     ` Georg Bauhaus
2009-08-05 15:58                       ` Isaac Gouy
2009-08-05 21:18                         ` Georg Bauhaus
2009-08-05 22:04                           ` Ludovic Brenta
2009-08-05 22:31                             ` Georg Bauhaus
2009-08-05 23:44                               ` Jeffrey R. Carter
2009-08-06  8:38                                 ` Georg Bauhaus
2009-08-06 21:39                                   ` Georg Bauhaus
2009-08-06 22:42                                     ` Jeffrey R. Carter
2009-08-07  8:53  2%                                   ` Georg Bauhaus
     [not found]     <4a9b045a$0$31875$9b4e6d93@newsspool3.arcor-online.net>
2009-08-31  8:28  0% ` Q: Line_IO Martin
2009-08-31 18:39     ` Dmitry A. Kazakov
2009-08-31 23:56  2%   ` Georg Bauhaus
2009-09-27  1:08  1% Tasking for Mandelbrot program Georg Bauhaus
2009-10-24 22:07     Preferred way to do binray I/O on standard input/output stream Hibou57 (Yannick Duchêne)
2009-10-24 22:57  2% ` Jeffrey R. Carter
2009-10-29 23:29  1% Performance of the Streams 'Read and 'Write Gautier write-only
2009-10-30 13:40  2% ` Gautier write-only
2009-11-02 22:19  2%   ` Gautier write-only
2010-01-04 22:46  2% Problem with streams using 64-bit compiler sjw
2010-05-07  1:02  2% Why is not Stream_Access defined Ada.Streams ? Yannick Duchêne (Hibou57)
2010-05-07  2:24  0% ` Randy Brukardt
2010-08-01 12:17     S-expression I/O in Ada Natacha Kerensikova
2010-08-01 16:01     ` Ludovic Brenta
2010-08-09 18:49       ` Ludovic Brenta
2010-08-09 19:59         ` Natacha Kerensikova
2010-08-10  0:11           ` Ludovic Brenta
2010-08-10  0:57             ` Jeffrey Carter
2010-08-10  6:47               ` Natacha Kerensikova
2010-08-10 18:13                 ` Jeffrey Carter
2010-08-12  9:26                   ` Natacha Kerensikova
2010-08-12 10:55  1%                 ` Ludovic Brenta
2010-08-12 23:26  1% ` Shark8
2010-08-20 23:23     Binary opperations under Ada? Trogdor
2010-08-21  0:17  2% ` Jeffrey Carter
2010-12-27 18:26     An Example for Ada.Execution_Time anon
2010-12-28  2:31     ` BrianG
2010-12-29  3:10  2%   ` Randy Brukardt
2010-12-30 23:51  1%     ` BrianG
2011-01-01  0:07  0%       ` Randy Brukardt
2011-05-24  1:39     Why no socket package in the standard ? Yannick Duchêne (Hibou57)
2011-05-24  6:11     ` tmoran
2011-05-25 15:12 14%   ` Tero Koskinen
2011-08-29 15:46     Address and bit mask milouz
2011-08-29 19:41     ` Ludovic Brenta
2011-08-29 19:54       ` Adam Beneschan
2011-08-30  9:14         ` milouz
2011-08-30 15:14           ` Adam Beneschan
2011-08-31  7:45             ` milouz
2011-08-31  8:35  3%           ` Ludovic Brenta
2011-12-15 18:13     Writing Data to a file awdorrin
2011-12-15 18:32  3% ` Ludovic Brenta
2012-03-25 14:28     xor Michael Moeller
2012-03-25 14:01     ` xor Niklas Holsti
2012-03-25 15:16       ` xor Michael Moeller
2012-03-25 19:26  1%     ` xor Niklas Holsti
2012-03-27 20:09  0%       ` xor Michael Moeller
2013-09-04 11:10     Calling a File for Encryption from outside of the Main Ada-95 Holding Folder Austin Obyrne
2013-09-04 19:37     ` Austin Obyrne
2013-09-04 19:47       ` Eryndlia Mavourneen
2013-09-04 20:37         ` Austin Obyrne
2013-09-04 21:31           ` Austin Obyrne
2013-09-05  5:39             ` Simon Wright
2013-09-05  7:56               ` Austin Obyrne
2013-09-05 11:33  1%             ` Simon Wright
2013-09-05 15:46  0%               ` Austin Obyrne
2013-09-05 16:00  0%               ` Austin Obyrne
2013-12-07 12:24     Will Ada-95 Programs Written in MS Windows Run in MacOS and Linux Without Some Tweaking Austin Obyrne
2013-12-07 13:16     ` Simon Wright
2013-12-07 14:01       ` Austin Obyrne
2013-12-07 17:18         ` Simon Wright
2013-12-07 18:26           ` Austin Obyrne
2013-12-08 17:17             ` Simon Wright
2013-12-10  6:37               ` Randy Brukardt
2013-12-11  0:34  2%             ` Simon Wright
2014-11-15 14:35  3% Ada.Containers warnings with gnat Björn Lundin
2014-11-15 18:01     ` Jeffrey Carter
2014-11-16 10:05       ` Björn Lundin
2014-11-16 11:37  3%     ` Björn Lundin
2014-11-16 17:32  0%       ` Jeffrey Carter
2014-11-17  8:13  3%         ` Björn Lundin
2014-11-17 16:39  0%           ` Anh Vo
2015-02-02  5:50  2% Did I find mamory leak in Generic Image Decoder (GID) ? reinkor
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  3%   ` Maciej Sobczak
2015-08-25 15:26  0%     ` Maciej Sobczak
2015-08-25 16:18  0%       ` J-P. Rosen
2015-08-25 16:45  3%       ` G.B.
2016-01-20  1:39     Out_File , excess line comicfanzine
2016-01-22 20:01  2% ` comicfanzine
2016-01-23 20:06  2% ` comicfanzine
2016-01-27  9:26  0%   ` Simon Wright
2016-01-27 20:28  0%     ` Dmitry A. Kazakov
2016-01-31  8:56     ` comicfanzine
2016-01-31 11:25       ` Simon Wright
2016-01-31 12:57  3%     ` Dmitry A. Kazakov
2016-08-12  4:05     How to write "Hello" to a text file without a line terminator Jerry
2016-08-12  7:23     ` Dmitry A. Kazakov
2016-08-12  7:44       ` Jerry
2016-08-12 17:34         ` Jeffrey R. Carter
2016-08-13  3:21           ` Jerry
2016-08-13  4:23             ` Jeffrey R. Carter
2016-08-13  9:12               ` AdaMagica
2016-08-13 18:03                 ` Jeffrey R. Carter
2016-08-14  7:58                   ` AdaMagica
2016-08-14  8:30                     ` Simon Wright
2016-08-14  8:54                       ` Dmitry A. Kazakov
2016-08-14  9:40  2%                     ` Simon Wright
2016-08-14 10:17  2%                       ` Dmitry A. Kazakov
2016-08-25 20:17     zLibAda vs ZipAda (which should I use, if any)? Aurele
2016-08-25 23:07     ` Aurele
2016-08-25 23:43       ` gautier_niouzes
2016-08-25 23:55         ` Aurele
2016-08-26  0:18           ` gautier_niouzes
2016-08-26  1:44             ` Aurele
2016-08-26 12:36               ` gautier_niouzes
2016-08-26 14:23                 ` Aurele
2016-08-26 15:16                   ` gautier_niouzes
2016-08-26 16:05                     ` Aurele
2016-08-26 23:04                       ` Aurele
2016-08-27  5:30                         ` gautier_niouzes
2016-08-27 11:52                           ` Aurele
2016-08-27 16:31  2%                         ` Aurele
2016-08-27 19:15  0%                           ` gautier_niouzes
2016-08-27 19:33  3% ` Aurele
2017-08-29 20:28     win32 interfacing check (SetClipboardData) Xavier Petit
2017-08-30 16:04     ` Dmitry A. Kazakov
2017-08-30 18:41       ` Xavier Petit
2017-08-30 21:17         ` Dmitry A. Kazakov
2017-09-01 12:51           ` Xavier Petit
2017-09-01 13:10  2%         ` Dmitry A. Kazakov
2017-09-02  9:38  0%           ` Xavier Petit
2017-09-02 12:29  0%             ` Dmitry A. Kazakov
2017-09-03 11:01     quiz for Sequential_IO Read Frank Buss
2017-09-03 12:26  2% ` Dmitry A. Kazakov
2017-09-03 12:43  0%   ` Frank Buss
2017-09-03 13:11  0%     ` Dmitry A. Kazakov
2017-09-04 19:58  3%       ` Frank Buss
2017-09-04 20:55  0%         ` Dmitry A. Kazakov
2017-10-21  2:05  2% Finding the end of a stream from a socket Andrew Shvets
2017-10-21  8:44  0% ` Dmitry A. Kazakov
2017-10-21 13:45  0%   ` Andrew Shvets
2017-10-21 17:34  0%   ` Andrew Shvets
2017-10-21 19:18  0%     ` Andrew Shvets
2018-02-21 23:57  2% article on acces types and dynamic serialization in Ada (2003) Mehdi Saada
2020-07-04 17:00     General circular buffer example not tied to any specific type Daniel
2020-09-24  4:10     ` nimaopatel121
2020-09-24  4:39  2%   ` J-P. Rosen
2021-03-22 17:13     surprise data from Ada.Sequential_IO John Perry
2021-03-22 17:48  2% ` Dmitry A. Kazakov
2021-06-27 19:33  2% Hi! How I can make _indexed_ stream file Input/Output ? Thanks Daniel Norte Moraes
2021-06-28  1:36  0% ` Dennis Lee Bieber
2021-07-02 20:57  0% ` Shark8
2021-07-05  4:06  0%   ` zac brown
2021-07-05  4:06  0%     ` zac brown
2022-01-14 18:30  2% Usage of Stream Set_Index() function DrPi
2022-01-14 20:35  0% ` Niklas Holsti
2022-01-15 10:36  0%   ` DrPi
2023-06-30 19:28  3% GNAT Community 2020 (20200818-93): Big_Integer Frank Jørgen Jørgensen
2023-06-30 21:07  2% ` Dmitry A. Kazakov

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