From mboxrd@z Thu Jan 1 00:00:00 1970 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on polar.synack.me X-Spam-Level: X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00 autolearn=ham autolearn_force=no version=3.4.4 X-Google-Language: ENGLISH,ASCII-7-bit X-Google-Thread: 103376,2e66fe8b30e3ee2c X-Google-Attributes: gid103376,public From: "David C. Hoos, Sr." Subject: Re: S'Write and How To Count Bytes Date: 2000/10/02 Message-ID: <8raqkp$74k$1@hobbes2.crc.com> X-Deja-AN: 676776910 References: <39D6891A.7DC448B6@acm.org> X-MimeOLE: Produced By Microsoft MimeOLE V5.50.4133.2400 X-Complaints-To: abuse@crc.com X-Trace: hobbes2.crc.com 970517977 7316 198.175.145.56 (2 Oct 2000 20:19:37 GMT) Organization: CRC: A wholly owned subsidiary of Thermo Electron NNTP-Posting-Date: 2 Oct 2000 20:19:37 GMT Newsgroups: comp.lang.ada Date: 2000-10-02T20:19:37+00:00 List-Id: 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" > To: "David C. Hoos, Sr." > 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" 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 >>> ====================================================================== >>> >>>