comp.lang.ada
 help / color / mirror / Atom feed
* Dynamic Array Sizing
@ 1999-06-19  0:00 Nick Wilson
  1999-06-19  0:00 ` jerry
                   ` (2 more replies)
  0 siblings, 3 replies; 11+ messages in thread
From: Nick Wilson @ 1999-06-19  0:00 UTC (permalink / raw)


Hello, I was wondering if anyone can help me with the following dilema,

I have a file containing an variable amount of data that I want to read
into an array. My problem is that if I use a dynamic array, eg

type Array_Store is array (integer range <>) of boolean;

I have to declare an actual array sometime before reading the values
into the array, but don't know what size to make the array. I can do two
passes of the file, one to see the size, then declare the array in a
block and do another pass to read the values into it.

My problem comes about when I want to use functions which are externally
available outside this package to lookup the array values. In order to
do so, I will need to have the funcitons inside the declare block so
they can access the array, but this doesn't seem possible ?
Is there a nicer way to do the above in ADA to get access to my array
from outside the package ?

Any help much appreciated, thanks






^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: Dynamic Array Sizing
  1999-06-19  0:00 Dynamic Array Sizing Nick Wilson
  1999-06-19  0:00 ` jerry
  1999-06-19  0:00 ` Tom Moran
@ 1999-06-19  0:00 ` Matthew Heaney
  1999-06-20  0:00   ` Nick Wilson
  2 siblings, 1 reply; 11+ messages in thread
From: Matthew Heaney @ 1999-06-19  0:00 UTC (permalink / raw)


On 19 Jun 1999 13:39, Nick Wilson <snow_moose@hotmail.com> wrote:

> I have a file containing an variable amount of data that I want to read
> into an array. My problem is that if I use a dynamic array, eg
> 
> type Array_Store is array (integer range <>) of boolean;

Any reason you're using an index subtype of Integer?  The usual Ada
idiom is to use Positive:

  type Array_Store is array (Positive range <>) of Boolean;


> I have to declare an actual array sometime before reading the values
> into the array, but don't know what size to make the array.

Is the number of values stored in the file, perhaps at a specific
offset?  Then you can read in the length, declare the array object, and
then read into the array:

  declare
    N : Positive;  -- or Natural?
  begin
    Read (File, N);  -- maybe use Direct_IO or Stream_IO
 
    declare
      Values : Array_Store (1 .. N);
    begin
      Read (File, Values);
    end;
  end;


> I can do two passes of the file, one to see the size, then declare the
> array in a block and do another pass to read the values into it.

Do you need to read in all the data at once (into an array)?  Can't you
just read the data from the file directly?

There's not much difference between reading from a randomly-accessed
array object, versus reading from a randomly-accessed file object.

If you don't need random access, then you could just use Sequential_IO.

 
> My problem comes about when I want to use functions which are
> externally available outside this package to lookup the array
> values. In order to do so, I will need to have the funcitons inside
> the declare block so they can access the array, but this doesn't seem
> possible ?  Is there a nicer way to do the above in ADA to get access
> to my array from outside the package ?

I don't know what you're trying to say here.  Post a snippet of code,
enough for us to see the module structure.


I don't think you need to read the data into an array.  Just read from
the file directly, using Direct_IO (for random-access) or Sequential_IO
(for sequential access).







^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: Dynamic Array Sizing
  1999-06-19  0:00 Dynamic Array Sizing Nick Wilson
@ 1999-06-19  0:00 ` jerry
  1999-06-19  0:00   ` jerry
  1999-06-19  0:00   ` Matthew Heaney
  1999-06-19  0:00 ` Tom Moran
  1999-06-19  0:00 ` Matthew Heaney
  2 siblings, 2 replies; 11+ messages in thread
From: jerry @ 1999-06-19  0:00 UTC (permalink / raw)


Nick Wilson <snow_moose@hotmail.com> wrote:

: I have a file containing an variable amount of data that I want to read
: into an array. My problem is that if I use a dynamic array, eg

: type Array_Store is array (integer range <>) of boolean;

: I have to declare an actual array sometime before reading the values
: into the array, but don't know what size to make the array. I can do two
: passes of the file, one to see the size, then declare the array in a
: block and do another pass to read the values into it.

If you are using GNAT, you could do something like:

--  * notes: - assumes 1-bit booleans
--           - using streams is slower

with GNAT.OS_Lib; use GNAT.OS_Lib;
with Ada.Text_IO; use Ada.Text_IO;

with Ada.Sequential_IO;
with Ada.Unchecked_Deallocation;

procedure Stuff is

   Data_Size_Error : exception;   --  no data in file
   File_Name_Error : exception;   --  file cannot be opened

   type Data_Storage_Type is array (Positive range <>) of Boolean;
   --  an array to store the data in

   type Data_Access is access all Data_Storage_Type;
   --  a pointer to the data

   procedure Free is new
     Ada.Unchecked_Deallocation (Data_Storage_Type, Data_Access);
   --  deallocate a data storage array

   package Boolean_File is new Ada.Sequential_IO (Boolean);
   use Boolean_File;
   --  package for using files of Booleans

   Data         : Data_Access;
   Num_Elements : Positive;
   File_Name    : constant String := "test.dat";

   -----------------------------------
   --  Get number of data elements  --
   -----------------------------------
   function Data_Elements (Path : String) return Positive is
      Fd     : File_Descriptor;
      Size   : Long_Integer;
      C_Name : String := Path & ASCII.NUL;
   begin
      Fd := Open_Read (C_Name'Address, Binary);
      if Fd = Invalid_FD then
         raise File_Name_Error;
      end if;
      Size := File_Length (Fd);
      Close (Fd);
      if Size < 1 then
         raise Data_Size_Error;
      end if;
      return Positive (Size);
   end Data_Elements;

   ------------------------------------------------------------
   --  Create data storage array and return a pointer to it  --
   ------------------------------------------------------------
   function Create_Data_Storage (Elements : Positive) return Data_Access is
      Storage : Data_Access;
   begin
      if Elements < 1 then
         raise Data_Size_Error;
      end if;
      Storage := new Data_Storage_Type (1 .. Elements);
      return Storage;
   end Create_Data_Storage;

   ---------------------------------------
   --  Read data in data storage array  --
   ---------------------------------------
   procedure Load_Data (Path : in String; Data : in Data_Access) is
      File : Boolean_File.File_Type;
   begin
      Open (File, In_File, Path);
      for I in 1 .. Data.all'Length loop
         Read (File, Data(I));
      end loop;
      Close (File);
   end Load_Data;

begin
   Num_Elements := Data_Elements (File_Name);
   Data := Create_Data_Storage (Num_Elements);
   Load_Data (File_Name, Data);
   Put_Line ("Loaded" & Data.all'Length'Img & " Booleans from " & File_Name);
   Free (Data);
end Stuff;

-- 
-- Jerry van Dijk | Leiden, Holland
-- Team Ada       | jdijk@acm.org
-- see http://stad.dsl.nl/~jvandyk




^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: Dynamic Array Sizing
  1999-06-19  0:00 ` jerry
@ 1999-06-19  0:00   ` jerry
  1999-06-19  0:00   ` Matthew Heaney
  1 sibling, 0 replies; 11+ messages in thread
From: jerry @ 1999-06-19  0:00 UTC (permalink / raw)


jerry@jvdsys.stuyts.nl wrote:

: --  * notes: - assumes 1-bit booleans

Whoops! Make that: 1-byte booleans !!!

-- 
-- Jerry van Dijk | Leiden, Holland
-- Team Ada       | jdijk@acm.org
-- see http://stad.dsl.nl/~jvandyk




^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: Dynamic Array Sizing
  1999-06-19  0:00 ` jerry
  1999-06-19  0:00   ` jerry
@ 1999-06-19  0:00   ` Matthew Heaney
  1999-06-19  0:00     ` jerry
  1 sibling, 1 reply; 11+ messages in thread
From: Matthew Heaney @ 1999-06-19  0:00 UTC (permalink / raw)


On 19 Jun 1999 11:16, jerry@jvdsys.stuyts.nl wrote:

> begin
>    Num_Elements := Data_Elements (File_Name);
>    Data := Create_Data_Storage (Num_Elements);
>    Load_Data (File_Name, Data);
>    Put_Line ("Loaded" & Data.all'Length'Img & " Booleans from " & File_Name);
>    Free (Data);
> end Stuff;


Why did you put the data on the heap?







^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: Dynamic Array Sizing
  1999-06-19  0:00 Dynamic Array Sizing Nick Wilson
  1999-06-19  0:00 ` jerry
@ 1999-06-19  0:00 ` Tom Moran
  1999-06-19  0:00 ` Matthew Heaney
  2 siblings, 0 replies; 11+ messages in thread
From: Tom Moran @ 1999-06-19  0:00 UTC (permalink / raw)


>type Array_Store is array (integer range <>) of boolean;

>I have to declare an actual array sometime before reading the values
>into the array, but don't know what size to make the array.
  You don't say if the array is a little thing or a very big thing.
How about declaring it "more than big enough" and then letting your
virtual memory simply never allocate any real memory for the part that
isn't used.

> functions which are externally
>available outside this package to lookup the array values. In order to
>do so, I will need to have the funcitons inside the declare block so
>they can access the array
  Could the functions be in a generic which is instantiated when the
needed size is known?




^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: Dynamic Array Sizing
  1999-06-19  0:00   ` Matthew Heaney
@ 1999-06-19  0:00     ` jerry
  1999-06-20  0:00       ` Matthew Heaney
  0 siblings, 1 reply; 11+ messages in thread
From: jerry @ 1999-06-19  0:00 UTC (permalink / raw)


Matthew Heaney <matthew_heaney@acm.org> wrote:

:> begin
:>    Num_Elements := Data_Elements (File_Name);
:>    Data := Create_Data_Storage (Num_Elements);
:>    Load_Data (File_Name, Data);
:>    Put_Line ("Loaded" & Data.all'Length'Img & " Booleans from " & File_Name);
:>    Free (Data);
:> end Stuff;

: Why did you put the data on the heap?

Why not ?

-- 
-- Jerry van Dijk | Leiden, Holland
-- Team Ada       | jdijk@acm.org
-- see http://stad.dsl.nl/~jvandyk




^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: Dynamic Array Sizing
  1999-06-19  0:00 ` Matthew Heaney
@ 1999-06-20  0:00   ` Nick Wilson
  1999-06-20  0:00     ` Matthew Heaney
  0 siblings, 1 reply; 11+ messages in thread
From: Nick Wilson @ 1999-06-20  0:00 UTC (permalink / raw)


>
> > I can do two passes of the file, one to see the size, then declare the
> > array in a block and do another pass to read the values into it.
>
> Do you need to read in all the data at once (into an array)?  Can't you
> just read the data from the file directly?
>
> There's not much difference between reading from a randomly-accessed
> array object, versus reading from a randomly-accessed file object.

The trouble comes about because it's a real time system and my understanding
is
that it would be a good idea to do as much of the initialisation before the
system
actually starts running. It would be possible to just open, read from the
file however
many times as necessary then close it until the next lookup. I'm just looking
for a
nicer way if I can.


>
> I don't know what you're trying to say here.  Post a snippet of code,
> enough for us to see the module structure.
>

-- spec
package Lookup_Array is
   function Get_Array_Size return Positive;
   procedure Initialise_Array;
   function Lookup_Value(Index : in Positive) is
end Lookup_Array;


-- body
package body Lookup_Array is

type Array_Store is array (Positive range <>) of Boolean;
Array_Size : Positive;

function Get_Array_Size return Positive is
    Open file
    Finds size of array
    return Array_Size := the size of array data in the file
end Get_Array_Size;

declare
    The_Array : Array_Store (Array_Size);

        procedure Initialise_Array is
            reads values from file into the array
        end Initialise_Array;

        function Lookup_Value(Index : in Positive) is
            return The_Array(Index);
        end Looup_Value;

end Lookup_Array;

I know this code isn't right, but hopefully it points out the problem of
where I can declare The_Array so that it is visible to outside calling
functions such as Lookup_Value ?





^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: Dynamic Array Sizing
  1999-06-19  0:00     ` jerry
@ 1999-06-20  0:00       ` Matthew Heaney
  1999-06-21  0:00         ` jerry
  0 siblings, 1 reply; 11+ messages in thread
From: Matthew Heaney @ 1999-06-20  0:00 UTC (permalink / raw)


On 19 Jun 1999 17:21, jerry@jvdsys.stuyts.nl wrote:

> Matthew Heaney <matthew_heaney@acm.org> wrote:
> : Why did you put the data on the heap?
> 
> Why not ?

Because Ada has constructs specifically designed to obviate the need for
heap.  

When you have a choice between putting an object on the heap versus the
stack, you should choose the stack.

You could have easily done this:

    Data : Array_Type (1 .. Data_Elements (File_Name));
  begin
    Load_Data (File_Name, Data);


Heap allocation is not necessary, nor is heap deallocation.








  




^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: Dynamic Array Sizing
  1999-06-20  0:00   ` Nick Wilson
@ 1999-06-20  0:00     ` Matthew Heaney
  0 siblings, 0 replies; 11+ messages in thread
From: Matthew Heaney @ 1999-06-20  0:00 UTC (permalink / raw)


On 20 Jun 1999 15:09, Nick Wilson <snow_moose@hotmail.com> wrote:

> The trouble comes about because it's a real time system and my
> understanding is that it would be a good idea to do as much of the
> initialisation before the system actually starts running. It would be
> possible to just open, read from the file however many times as
> necessary then close it until the next lookup. I'm just looking for a
> nicer way if I can.

No, you don't have to open and re-open the file during run-time.  File
init can be done once, at system start-up.  See the code below.

 
> package Lookup_Array is
>    function Get_Array_Size return Positive;
>    procedure Initialise_Array;
>    function Lookup_Value(Index : in Positive) is
> end Lookup_Array;
> 
> 
> -- body
> package body Lookup_Array is
> 
> type Array_Store is array (Positive range <>) of Boolean;
> Array_Size : Positive;
> 
> function Get_Array_Size return Positive is
>     Open file
>     Finds size of array
>     return Array_Size := the size of array data in the file
> end Get_Array_Size;
> 
> declare
>     The_Array : Array_Store (Array_Size);
> 
>         procedure Initialise_Array is
>             reads values from file into the array
>         end Initialise_Array;
> 
>         function Lookup_Value(Index : in Positive) is
>             return The_Array(Index);
>         end Looup_Value;
> 
> end Lookup_Array;
> 
> I know this code isn't right, but hopefully it points out the problem of
> where I can declare The_Array so that it is visible to outside calling
> functions such as Lookup_Value ?


Some comments:

o If you insist on declaring a local array, then you can do it during
  package elaboration:

  package body Lookup_Array is

    function Get_Array_Size return Positive is ...;

    The_Array : Array_Storage (1 .. Get_Array_Size);

    function Lookup_Value ... is;

  begin

    <read values from file and populate The_Array>

  end Lookup_Array;


o The client of the package doesn't care whether he's reading from a
  a local array or from the file directly.  Since he's already calling a
  function to return a value, why not just implement the function to
  return a value from the file directly:

  package body Lookup_Array is

    File : <direct io>.File_Type;

    function Lookup_Value (Index : Positive) is
  
      Value : <value type>;

    begin
      
      Read (File, Index, Value);

      return Value;

    end Lookup_Value;

  begin

    Open (File, In_File, "myfile.dat");

  end Lookup_Array;


No local array is necessary.  And all initialization is done once,
during elaboration, so there's no run-time penalty.








^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: Dynamic Array Sizing
  1999-06-20  0:00       ` Matthew Heaney
@ 1999-06-21  0:00         ` jerry
  0 siblings, 0 replies; 11+ messages in thread
From: jerry @ 1999-06-21  0:00 UTC (permalink / raw)


Matthew Heaney <matthew_heaney@acm.org> wrote:

:> : Why did you put the data on the heap?
:> 
:> Why not ?

: Because Ada has constructs specifically designed to obviate the need for
: heap.  
: When you have a choice between putting an object on the heap versus the
: stack, you should choose the stack.

Using the same logic I can claim that Ada has specific facilities for
managing heap based objects, so one should avoid putting data on the
stack :-) :-)

Reality is that either is possible, and that the choice made will depend
on the problem domain, requirements and local standards.

In this example I see no problem in using the heap. I you are really
affraid of undeallocated memory, make the type controlled and override
the Finalize procedure.

regards,
Jerry.

-- 
-- Jerry van Dijk | Leiden, Holland
-- Team Ada       | jdijk@acm.org
-- see http://stad.dsl.nl/~jvandyk




^ permalink raw reply	[flat|nested] 11+ messages in thread

end of thread, other threads:[~1999-06-21  0:00 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
1999-06-19  0:00 Dynamic Array Sizing Nick Wilson
1999-06-19  0:00 ` jerry
1999-06-19  0:00   ` jerry
1999-06-19  0:00   ` Matthew Heaney
1999-06-19  0:00     ` jerry
1999-06-20  0:00       ` Matthew Heaney
1999-06-21  0:00         ` jerry
1999-06-19  0:00 ` Tom Moran
1999-06-19  0:00 ` Matthew Heaney
1999-06-20  0:00   ` Nick Wilson
1999-06-20  0:00     ` Matthew Heaney

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