comp.lang.ada
 help / color / mirror / Atom feed
* Writing Data to a file
@ 2011-12-15 18:13 awdorrin
  2011-12-15 18:32 ` Ludovic Brenta
  0 siblings, 1 reply; 5+ messages in thread
From: awdorrin @ 2011-12-15 18:13 UTC (permalink / raw)


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?



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

* Re: Writing Data to a file
  2011-12-15 18:13 Writing Data to a file awdorrin
@ 2011-12-15 18:32 ` Ludovic Brenta
  2011-12-15 19:23   ` awdorrin
  0 siblings, 1 reply; 5+ messages in thread
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	[flat|nested] 5+ messages in thread

* Re: Writing Data to a file
  2011-12-15 18:32 ` Ludovic Brenta
@ 2011-12-15 19:23   ` awdorrin
  2011-12-16  0:55     ` Randy Brukardt
  2011-12-16 13:30     ` Jacob Sparre Andersen
  0 siblings, 2 replies; 5+ messages in thread
From: awdorrin @ 2011-12-15 19:23 UTC (permalink / raw)



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


The buffer is a block of memory that contains data, it could be text,
integers, bytes, floating point numbers, whatever.
The AREA_PTR is the starting address of the memory block.
READ_OFFSET is the location within that block that we want to start
reading from while
WRITE_OFFSET is the last location in the buffer that was written to.

So since all I have is a System.Address and offsets, I believe I have
to cast/convert this a Stream_Element_Array.

If I could only access POSIX.IO's write 'function', rather than the
procedures, I wouldn't have to go through these hoops.
Of course, that write function is the equivalent of what I'm trying to
replace...

I'm not sure I see how the Stream_IO package could be used directly
for this.






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

* Re: Writing Data to a file
  2011-12-15 19:23   ` awdorrin
@ 2011-12-16  0:55     ` Randy Brukardt
  2011-12-16 13:30     ` Jacob Sparre Andersen
  1 sibling, 0 replies; 5+ messages in thread
From: Randy Brukardt @ 2011-12-16  0:55 UTC (permalink / raw)


"awdorrin" <awdorrin@gmail.com> wrote in message 
news:530c4f5e-3c00-4ad5-92de-a4faefad468d@p16g2000yqd.googlegroups.com...

...
>So since all I have is a System.Address and offsets, I believe I have
>to cast/convert this a Stream_Element_Array.

Yes, probably.

>If I could only access POSIX.IO's write 'function', rather than the
>procedures, I wouldn't have to go through these hoops.
>Of course, that write function is the equivalent of what I'm trying to
>replace...

You're not making any sense. The only difference between the POSIX.IO 
procedures and the imported function is that POSIX.IO gets rid of the 
(unused) result. The parameters and the meaning are the same (I think - I 
haven't used POSIX interfaces ever).

>I'm not sure I see how the Stream_IO package could be used directly
>for this.

Once you've converted your address/length into a Stream_Element_Array, just 
call Write on the appropriate slice:

    Stream_IO.Write (File_Object, Buf (1 .. Buf_Last));

or even (given that your sample code already has set the correct length:

   Stream_IO.Write (File_Object, Buf);

The "problem" here is getting a Stream_IO file object rather than a handle 
(which means you'll need to change the Open/Create calls, wherever they 
are), but that should be pretty simple.

                                   Randy.

P.S. In looking at your original code, I realized that you never gave 
Buf_Last a value, so that's probably why your Write call is failing. (You're 
writing some random number of bytes, rather than the correct calculated 
number).

P.P.S. In Janus/Ada, at least, the address clause would not work because you 
would relocate the array descriptor rather than the data. GNAT probably is 
different on this point, but I would not be certain if the clause works.

P.P.P.S. The use of explicit Address should be avoided in new code, 
specifically because it is hard to do anything sensible with it. Use general 
access types (if the designated value is of a specific type) it at all 
possible. (And if not, I recommend use of A2A 
(Address_to_Access_Conversions - see 13.7.2).







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

* Re: Writing Data to a file
  2011-12-15 19:23   ` awdorrin
  2011-12-16  0:55     ` Randy Brukardt
@ 2011-12-16 13:30     ` Jacob Sparre Andersen
  1 sibling, 0 replies; 5+ messages in thread
From: Jacob Sparre Andersen @ 2011-12-16 13:30 UTC (permalink / raw)


awdorrin <awdorrin@gmail.com> writes:

> The buffer is a block of memory that contains data, it could be text,
> integers, bytes, floating point numbers, whatever.

   type Whatever is ...;
   Buffer_Size : constant Natural := ...;
   type Buffer is array (1 .. Buffer_Size);

> The AREA_PTR is the starting address of the memory block.

   Area_Ptr : constant System.Address := ...;
   Data     : Buffer;
   for Data'Address use Area_Ptr;

> So since all I have is a System.Address and offsets, I believe I have
> to cast/convert this a Stream_Element_Array.

No need.  Just make sure your Ada data structure is located at the right
address (and has the right layout).

Jacob
-- 
�Great minds discuss ideas,
 Average minds discuss events,
 Small minds discuss people.�



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

end of thread, other threads:[~2011-12-16 13:30 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-12-15 18:13 Writing Data to a file awdorrin
2011-12-15 18:32 ` Ludovic Brenta
2011-12-15 19:23   ` awdorrin
2011-12-16  0:55     ` Randy Brukardt
2011-12-16 13:30     ` Jacob Sparre Andersen

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