comp.lang.ada
 help / color / mirror / Atom feed
From: "David C. Hoos, Sr." <david.c.hoos.sr@ada95.com>
Subject: Re: S'Write and How To Count Bytes
Date: 2000/10/02
Date: 2000-10-02T20:19:37+00:00	[thread overview]
Message-ID: <8raqkp$74k$1@hobbes2.crc.com> (raw)
In-Reply-To: 39D6891A.7DC448B6@acm.org

In my original answer, I gave a solution specific to your example, but there
is another technique I use for more general cases.

This technique uses a package I call Stream_Element_array_Streams, which
reads or writes to a region of memory defined by two parameters of
System.Address type.  The package has a procedure called Allow_Access
which defines the two address parameters, and whether the operation for
which
access is allowed is Read or Write.

This package maintains an index (initialized to 1 by the Allow_Access
procedure),
pointing to the next element on which the allowed operation would take
place.

Thus, after writing to this memory stream, the Index function of the package
can be
called to ascertain the number of bytes written.

The actual write to the file or communications channel, can be done with
Stream_Element_Array'Write, having been preceded by a call to Natural'Write
to
put the size on the stream first.

One situation for which I use this technique is the reading of DIS PDUs from
a UDP
port, where the Ada type has discriminants whose values are defined by the
values
of octets at a fixed offset from the start of the PDU.  Thus, I read the PDU
using a
package which delivers me a stream_element_array containing all of the
octets of
the  UDP packet. Then, I declare the object with the discriminant obtained
from the
appropriate elements of that array, and finally read from the raw memory
array into
the Ada (tagged) type, using my Stream_Element_Array_Streams package.

The reason I did not suggest the use of 'Input and 'Output (as suggested by
Dr. Schroer) is that you indicated only that you wanted the _length_ of the
stream
of bytes produced by the 'Write, whereas 'Input and 'Output write the 'First
and 'Last
for arrays, and in general insert all discriminants and/or bounds into the
stream.

I know this has been wordy, but I hope it helps.

> ----- Original Message -----
> From: "Marin David Condic" <mcondic.nospam@acm.org>
> To: "David C. Hoos, Sr." <david.c.hoos.sr@ada95.com>
> Sent: Monday, October 02, 2000 7:37 AM
> Subject: RE: S'Write and How To Count Bytes

> Well, there are a couple of questions here. One if which is "How does
> 'Write" normally handle an Unbounded_String or any other private type for
> that matter?" The ARM says they are defined for any non-limited type (ARM
> 13.13.2{36}) but I could easily see a private type (or any type)
containing
> Access variables - no mention of that. It mentions Elementary types, Array
> types, Record types, but not Access types. (Or is Access an Elementary
type?
> If so, its still a special case) Obviously, transmitting Access variables
is
> *not* a good idea. (What if I store an unbounded string using Stream_IO?
Is
> it going to come back properly, or will I have just stored a now-useless
> access variable that used to point to the string?)

> The other question is: "What if you extended the type and still wanted to
> handle the general case with dispatching => T'Class'Write?" That's really
> what I want to do - not so much a specific case of Unbounded_Strings. In
> other words, I need to somehow get the number of bytes I'm transmitting
into
> the stream and I can't count on the listener at the other end to be using
> Ada or anything else. (The device expects one of several messages with
> varying lengths - it needs the number of bytes as the first datum to
> correctly read all the data for the message before attempting to process
> it.) I believe I can use the 'Read and 'Write attributes to correctly get
> the individual data pieces into the stream, but I need to know how many
> bytes that is going to be before putting it in the stream. So far as I can
> tell, there is no way to do this except convert it to a stream, count the
> bytes that turned into, insert the byte count in the record, then convert
it
> to a stream again. Awfully wasteful!

> Maybe for Ada0x, there should be an attribute T'Stream_Size and/or
> T'Class'Stream_Size. Not sure that this would not simply have to
degenerate
> to converting everything and counting it in the background though.
>
> Thanks for the help.

> MDC

>> -----Original Message-----
>> From: David C. Hoos, Sr. [mailto:david.c.hoos.sr@ada95.com]
>> Sent: Monday, October 02, 2000 12:15 AM
>> To: mcondic.nospam@acm.org
>> Subject: Re: S'Write and How To Count Bytes

>> If your record contains an unbounded string, I would in the
My_Record'Write
>> procedure convert the unbounded string to a Standard.String, and write
its
>> length to the stream with Natural'Write, followed by a call to
String'Write.
>> This will put the length of the string on the stream, followed by the
>> string itself.

>> Then, the My_Record'Read procedure would read the length from the stream,
>> using Natural'Read, use that length to declare a string of the proper
size
>> (in a declare block), then read the string with String'Read.
>> Finally, you would convert the string to the unbounded string component
in
>> your My_Record'Read's out parameter of type My_Record.

"Marin David Condic" <mcondic.nospam@acm.org> wrote in message
news:39D6891A.7DC448B6@acm.org...
>>> Suppose I have a type something like this:
>>>
>>>     type My_Record is record
>>>         A_String    : Unbounded_String := Null_Unbounded_String ;
>>>     end record ;
>>>
>>> In theory, I should be able to create an object that is derived from
>>> Ada.Streams.Root_Stream_Type which has a Read and Write procedure that
>>> will allow me to create a call such as:
>>>
>>>     My_Record'Write (Ptr, A_Record) ;
>>>
>>> where Ptr is a pointer to my derived Root_Stream_Type object. Now here's
>>> where it gets fun:
>>>
>>> The object derived from Root_Stream_Type is going to contain some
>>> version of a Stream_Element_Array. Possibly dynamically allocated. The
>>> Write procedure that I create for the Root_Stream_Type is going to get
>>> automagically called with a Stream_Element_Array parameter, from which
>>> you could determine the size, allocate what you need for a buffer and
>>> attach it to the Root_Stream_Type. That buffer can then be sent
>>> somewhere or used in some other manner.
>>>
>>> The problem is this: What if you want the record to contain the number
>>> of bytes that it converts to so that the number ends up in the stream?
>>> You can't easily determine how many bytes there will be in the record
>>> nor can you determine what the 'Write is really going to produce. You
>>> could possibly retain the size information in your Root_Stream_Type
>>> after the conversion, but by then its too late. You already converted it
>>> and if you had a "Count" field in the record, its value is probably dead
>>> wrong. You could convert it to the stream once, interrogate the
>>> Root_Stream_Type you built to determine the number of bytes in it, then
>>> include that byte count in your record and convert it all over again.
>>> That seems a little inefficient.
>>>
>>> Is there any good way of determining in advance how many bytes you are
>>> going to get when converting an object to a stream?
>>>
>>> MDC
>>> --
>>> ======================================================================
>>> Marin David Condic - Quadrus Corporation - http://www.quadruscorp.com/
>>> Send Replies To: m c o n d i c @ q u a d r u s c o r p . c o m
>>> Visit my web site at:  http://www.mcondic.com/
>>>
>>>     "Giving money and power to Government is like giving whiskey
>>>     and car keys to teenage boys."
>>>
>>>         --   P. J. O'Rourke
>>> ======================================================================
>>>
>>>






  parent reply	other threads:[~2000-10-02  0:00 UTC|newest]

Thread overview: 29+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2000-09-30  0:00 S'Write and How To Count Bytes Marin David Condic
2000-10-01  0:00 ` David C. Hoos, Sr.
2000-10-02  0:00   ` Dr. Joachim Schr�er
2000-10-02  0:00     ` Marin David Condic
2000-10-06  0:00       ` Charles Hixson
2000-10-02  0:00   ` Marin David Condic
2000-10-02  0:00     ` Ted Dennison
2000-10-02  0:00       ` tmoran
2000-10-02  0:00         ` tmoran
2000-10-02  0:00           ` Ted Dennison
2000-10-02  0:00           ` Marin David Condic
2000-10-11  0:00             ` Nick Roberts
2000-10-11  0:00               ` Marin David Condic
2000-10-02  0:00         ` Marin David Condic
2000-10-03  0:00       ` Robert A Duff
2000-10-06  0:00         ` Randy Brukardt
2000-10-07  0:11           ` Ted Dennison
2000-10-06  0:00             ` Randy Brukardt
2000-10-07  0:00             ` Marin David Condic
2000-10-08  0:00               ` Jean-Pierre Rosen
2000-10-09  0:00                 ` Randy Brukardt
2000-10-11  0:00                 ` Marin David Condic
2000-10-02  0:00 ` David C. Hoos, Sr. [this message]
2000-10-02  6:58 ` tmoran
2000-10-02  0:00   ` Marin David Condic
  -- strict thread matches above, loose matches on Subject: below --
2000-10-02  0:00 tmoran
2000-10-03  5:21 ` Marin David Condic
2000-10-03  0:00 Mario Amado Alves
2000-10-03  0:00 ` Marin David Condic
replies disabled

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