To make myself more clear I have already dealt with the serial comms
bit, I am looking to display the stream I have already captured
You could use the predefined library to get a result using the Ada
"syntax for based literal" (ARM A.10.8(14)), e.g. 16#CE#.
package Stream_Element_IO is
new Ada.Text_IO.Modular_IO (Num => Ada.Streams.Stream_Element);
E : Ada.Streams.Stream_Element := ...
begin
Stream_Element_IO.Put (Item => E, Base => 16);
(There are variants of Put that send the output to a File_Type or to a
string).
If you want to avoid the 16## part, you can easily convert the
stream_elements to a string representation yourself like so:
function To_Hex (E : in Ada.Streams.Stream_Element) return String is
-- Warning: not compiled and not tested...
X : constant array (0 .. 15) of Character :=
('0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C',
'D', 'E', 'F');
Result : String (1 .. Ada.Streams.Stream_Element'Size / 4); -- 1
hex digits = 4 bits
Working_Copy : Ada.Streams.Stream_Element := E;
use type Ada.Streams.Stream_Element;
First_Character : Natural := 0;
Base : constant := 16;
begin
for K in reverse Result'Length loop
Result (K) := X (Working_Copy mod Base);
Working_Copy := Working_Copy / Base;
if Working_Copy = 0 then
First_Character := K;
exit;
end if;
end loop;
return Result (First_Character .. Result'Last);
end To_Hex;
Hope this helps.
--
Ludovic Brenta.
Thanks Ludovic I'll try that.
I tried the first way and thought I would prefer the hex.
I got an error as the compiler is expecting a second value in the
range.
Second way is definetly the way forward I think , Thanks again for a
very detailed reply, its saved me loads of time :)
Here's one approach that's convenient for command line use:
<http://sites.google.com/site/drjohnbmatthews/hexdump>
--
John B. Matthews
trashgod at gmail dot com
<http://sites.google.com/site/drjohnbmatthews>
Changed the hex function to
function To_Hex (E : in Ada.Streams.Stream_Element) return String
is
-- Warning: not compiled and not tested...
X : constant array (0 .. 15) of Character :=
('0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B',
'C', 'D', 'E', 'F');
Result : String (1 .. Ada.Streams.Stream_Element'Size / 4); -- 1
hex digits = 4 bits
Working_Copy : Ada.Streams.Stream_Element := E;
use type Ada.Streams.Stream_Element;
First_Character : Natural := 0;
Base : constant := 16;
begin
for K in reverse Result'First .. Result'Length loop
Result (K) := X (integer(Working_Copy) mod integer (Base) );
Working_Copy := Working_Copy / Base;
if Working_Copy = 0 then
First_Character := K;
exit;
end if;
end loop;
return Result (First_Character .. Result'Last);
end To_Hex;
It still seems to be dropping a few zeros though and I'm stumped where
its going wrong
The following is based on:
http://www.dmitry-kazakov.de/ada/strings_edit.htm
with Ada.Streams; use Ada.Streams;
with Strings_Edit; use Strings_Edit;
with Strings_Edit.Integers; use Strings_Edit.Integers;
function Image (Data : Stream_Element_Array) return String is
begin
if Data'Length = 0 then
return "";
end if;
declare
Text : String (1..Data'Length * 3);
Pointer : Integer := 1;
begin
for I in Data'Range loop
Put
( Text, Pointer, Stream_Element'Pos (Data (I)),
Field=>2, Fill=>'0', Justify=>Right, Base=>16
);
Put (Text, Pointer, ' ');
end loop;
return Text (1..Text'Last - 1);
end;
end Image;
An individual item is output
Put
( Text, Pointer, Stream_Element'Pos (Item),
Field=>2, Fill=>'0', Justify=>Right, Base=>16
);
--
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de
Thanks Guys, I forgot how helpful these forums were and how many
people out there used Ada, you reminded me, and I got some working
code \o/
..
> You could use the predefined library to get a result using the Ada
> "syntax for based literal" (ARM A.10.8(14)), e.g. 16#CE#.
>
> package Stream_Element_IO is
> new Ada.Text_IO.Modular_IO (Num => Ada.Streams.Stream_Element);
>
> E : Ada.Streams.Stream_Element := ...
> begin
> Stream_Element_IO.Put (Item => E, Base => 16);
>
> (There are variants of Put that send the output to a File_Type or to a
> string)..
> Ludovic Brenta.
I've been interested in finding these ways to "Put" (Hex) to
a string, instead of a File_Type.
But what I've seen is that "Put" always involves a
File_Type (or implies one).
So what have I missed?
Warren
From A.10.8 (Input-Output for Integer Types):
15
procedure Get(From : in String; Item : out Num; Last : out Positive);
16
Reads an integer value from the beginning of the given string,
following the same rules as the Get procedure that reads an integer
value from a file, but treating the end of the string as a file
terminator. Returns, in the parameter Item, the value of type Num that
corresponds to the sequence input. Returns in Last the index value
such that From(Last) is the last character read.
17
The exception Data_Error is propagated if the sequence input does not
have the required syntax or if the value obtained is not of the
subtype Num.
18
procedure Put(To : out String;
Item : in Num;
Base : in Number_Base := Default_Base);
19
Outputs the value of the parameter Item to the given string, following
the same rule as for output to a file, using the length of the given
string as the value for Width.
> On Apr 19, 11:05�am, Warren <ve3...@gmail.com> wrote:
>>
>> I've been interested in finding these ways to "Put" (Hex) to
>> a string, instead of a File_Type.
>>
>> But what I've seen is that "Put" always involves a
>> File_Type (or implies one).
>>
>> So what have I missed? �
>
> From A.10.8 (Input-Output for Integer Types):
...
> procedure Put(To : out String;
> Item : in Num;
> Base : in Number_Base := Default_Base);
> 19
> Outputs the value of the parameter Item to the given string, following
> the same rule as for output to a file, using the length of the given
> string as the value for Width.
My apologies-- I see it now. I hate these dos names
that gnat uses for the spec file names. I see the
api now.
Now if only I could find where the mayonnaise in the
fridge is..
Warren
This seems unnecessarily complex to me. Using the standard library to
put an element to a String in base 16, then stripping the "16#" from
the front and '#' from the end seems simpler, clearer, and less error
prone.
The PragmAda Reusable Components include Image functions with optional
Width, Zero_Filled, and Base parameters that do not include any base
indicator in the image. See PragmARC.Images and PragmARC.Images.Image.
(1) I should have written:
X : constant array (Ada.Streams.Stream_Element range 0 .. 15) of Character :=
> ('0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B',
> 'C', 'D', 'E', 'F');
> Result : String (1 .. Ada.Streams.Stream_Element'Size / 4); -- 1 hex digits = 4 bits
> Working_Copy : Ada.Streams.Stream_Element := E;
> use type Ada.Streams.Stream_Element;
> First_Character : Natural := 0;
> Base : constant := 16;
> begin
> for K in reverse Result'First .. Result'Length loop
(2) and this should be:
for K in reverse Result'Range loop
> Result (K) := X (integer(Working_Copy) mod integer (Base) );
(3) and thanks to (1), this can come back to the simpler:
Result (K) := X (Working_Copy mod Base);
> Working_Copy := Working_Copy / Base;
> if Working_Copy = 0 then
> First_Character := K;
> exit;
> end if;
> end loop;
> return Result (First_Character .. Result'Last);
> end To_Hex;
>
> It still seems to be dropping a few zeros though and I'm stumped where
> its going wrong
I tested it with 42 and 0 and correctly got 2A and 0, so I don't know
what you mean by that.
Maybe the fact that the result has a variable width is a problem? If
so, here is a fixed-width variant which is actually a bit simpler:
function To_Hex (E : in Ada.Streams.Stream_Element) return String is
X : constant array (Ada.Streams.Stream_Element range 0 .. 15)
of Character :=
('0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C',
'D', 'E', 'F');
Result : String
(1 .. Ada.Streams.Stream_Element'Size / 4) -- 1 hex digits = 4 bits
:= (others => '0');
Working_Copy : Ada.Streams.Stream_Element := E;
use type Ada.Streams.Stream_Element;
Base : constant := 16;
begin
for K in reverse Result'Range loop
Result (K) := X (Working_Copy mod Base);
Working_Copy := Working_Copy / Base;
end loop;
return Result;
end To_Hex;
and this yields 2A and 00 for my "test vector".
--
Ludovic Brenta.
> On Apr 19, 9:24 am, Ludovic Brenta <ludo...@ludovic-brenta.org> wrote:
>>
>> If you want to avoid the 16## part, you can easily convert the
>> stream_elements to a string representation yourself like so:
>>
>> function To_Hex (E : in Ada.Streams.Stream_Element) return String is
>
> This seems unnecessarily complex to me. Using the standard library to
> put an element to a String in base 16, then stripping the "16#" from
> the front and '#' from the end seems simpler, clearer, and less error
> prone.
I find it funny you should say that because I thought exactly the
opposite: letting Ada.Text_IO (which is notoriously slow) do the
conversion to string and then doing string manipulation is less clear
and more error-prone, IMHO (a proper implementation would use a simple,
but full-fledged, finite state machine). But your approach is certainly
valid and correct nevertheless.
--
Ludovic Brenta.
> I hate these dos names that gnat uses for the spec file names.
Same here. Using GNAT, `gnatkr` can be used to find a file from a name
in the API. Say you are reading "A.10.1 The Package Text_IO", you can
pull up the specification with a command such as this:
$ more $ADA_INC/$(gnatkr Ada.Text_IO.ads)
where $ADA_INC point to the run-time library include files.
<http://gcc.gnu.org/onlinedocs/gcc-4.5.0/gnat_ugn_unw/File-Name-Krunching-Using-gnatkr.html>
It got shoved in the back, behind that leftover chicken casserole
that's been there way too long and needs to be thrown out.
Hope this helps,
-- Adam
Funny you should say that ...
Considering that I can write
function Hex_Image (Number : Ada.Streams.Stream_Element) return String
is
Result : String (1 .. 10);
Start : Natural;
package Stream_Element_IO is new Ada.Text_IO.Modular_IO (Num =>
Ada.Streams.Stream_Element);
begin -- Hex_Image
Stream_Element_IO.Put (To => Result, Item => Number, Base => 16);
Start := Ada.Strings.Fixed.Index (Result, "#") + 1;
return Result (Start .. Result'Last - 1);
end Hex_Image;
and get it right 1st time, compared to the issues you encountered
duplicating (some of) the functionality of Put, seems to me evidence
that this approach is less error prone. I certainly find it simpler
and clearer, too.
Getting this to return a zero-filled String of the correct number of
digits is slightly more complex:
Num_Chars : constant := Ada.Streams.Stream_Element'Size / 4;
Result : String (1 .. Num_Chars + 10);
...
return String'(1 .. Num_Chars - (Result'Last - Start) => '0') & Result
(Start .. Result'Last - 1);
Just to chime in with my generic solution to this (from SAL
http://www.stephe-leake.org/ada/sal.html) :
pragma License (Modified_GPL);
generic
Width : Natural;
type Number_Type is mod <>;
function SAL.Generic_Hex_Image (Item : in Number_Type) return String;
-- Return a hexadecimal image of Item, padded with leading zeros to
-- Width. If Width is too small for Item, leading digits are silently
-- truncated.
pragma Pure (SAL.Generic_Hex_Image);
function SAL.Generic_Hex_Image (Item : in Number_Type) return String
is
Temp : Number_Type := Item;
Nibble : Number_Type;
Image : String (1 .. Width);
begin
for I in reverse Image'Range loop
Nibble := Temp mod 16;
Temp := Temp / 16;
if Nibble > 9 then
Image (I) := Character'Val (Character'Pos ('A') + Integer (Nibble) - 10);
else
Image (I) := Character'Val (Character'Pos ('0') + Integer (Nibble));
end if;
end loop;
return Image;
end SAL.Generic_Hex_Image;
--
-- Stephe
Its the variable width I think.
http://en.wikipedia.org/wiki/Netiquette
and
http://tools.ietf.org/html/rfc1855
for postings, look for:
But do not include the entire original!
alternative: many CTRL-K
..
>> Now if only I could find where the mayonnaise in the
>> fridge is..
>
> It got shoved in the back, behind that leftover chicken casserole
> that's been there way too long and needs to be thrown out.
>
> Hope this helps,
>
> -- Adam
Ew!
I guess it helps not to have preconceptions when looking
for stuff. I looked for a "white" jar of mayonnaise and of
course couldn't find it. This was because my wife bought
mayonnaise in a yellow plastic jar (recently), which I
mistook for mustard. She of course, had no trouble at
all finding it.
Warren
> I guess it helps not to have preconceptions when looking
> for stuff. I looked for a "white" jar of mayonnaise and of
> course couldn't find it. This was because my wife bought
> mayonnaise in a yellow plastic jar (recently), which I
> mistook for mustard. She of course, had no trouble at
> all finding it.
>
Now, you understand the importance of having unambiguous specifications
that match the implementation (back on topic) ;-)
--
---------------------------------------------------------
J-P. Rosen (ro...@adalog.fr)
Visit Adalog's web site at http://www.adalog.fr
> Warren a écrit :
>
>> I guess it helps not to have preconceptions when looking
>> for stuff. I looked for a "white" jar of mayonnaise and of
>> course couldn't find it. This was because my wife bought
>> mayonnaise in a yellow plastic jar (recently), which I
>> mistook for mustard. She of course, had no trouble at
>> all finding it.
>>
> Now, you understand the importance of having unambiguous specifications
> that match the implementation (back on topic) ;-)
Indeed!
with Fridge.Mayonnaise;
Warren
So if I sometimes want different widths for the same type, I have to
have multiple instantiations? That doesn't seem very friendly to me. I
don't see why Width couldn't be a parameter of the function, probably
defaulted to Number_Type'Width.
What do I do for signed integer images, for bases other than 16, and
for signed integer images for bases other than 16? Do I have to roll
my own for these cases?
In Ada.Text_IO, a Width of zero implies the minimum width needed to
represent the value; here it's an expensive way to get a null String.
I'd prefer consistency with the standard.
I haven't used SAL, but these are the kind of comments you'd probably
get from me if I did use this function. HTH.
> On Apr 20, 12:25 am, Stephen Leake <stephen_le...@stephe-leake.org>
> wrote:
>>
>> generic
>> Width : Natural;
>> type Number_Type is mod <>;
>> function SAL.Generic_Hex_Image (Item : in Number_Type) return String;
>> -- Return a hexadecimal image of Item, padded with leading zeros to
>> -- Width. If Width is too small for Item, leading digits are silently
>> -- truncated.
>
> So if I sometimes want different widths for the same type, I have to
> have multiple instantiations?
Yes. But in practice, the width you want is Number_Type'Width (but
assuming hexadecimal), so it's not a problem.
The only problem I've encountered is the "silently truncated" part. We
changed a number type to have more bits, but forgot to change the Width
parameter here.
There are times, such as building formatted dates, when I need a
specific number of characters, and want an exception if the actual value
can't be represented in that number. Then this function is not
appropriate.
> That doesn't seem very friendly to me. I don't see why Width couldn't
> be a parameter of the function,
It could; in the body, it is only used as the size of the result image
string. It's just historical accident that it is a generic parameter
instead.
> probably defaulted to Number_Type'Width.
That assumes base 10, so it would be wrong. If I made a change like
this, I'd keep the generic parameter as the default width, or add a
function that computes a default width assuming base 16, and use that as
the default.
> What do I do for signed integer images,
I never need to image signed integers in hex; that's confusing.
> for bases other than 16,
sal-generic_binary_image.ads
sal-generic_decimal_image.ads
are the only ones I've ever needed. The binary image includes '_' every
four digits.
> and for signed integer images for bases other than 16?
Never needed them.
> Do I have to roll my own for these cases?
Yes.
It is far easier to test a small, focused routine than a large, general
purpose one.
> In Ada.Text_IO, a Width of zero implies the minimum width needed to
> represent the value; here it's an expensive way to get a null String.
> I'd prefer consistency with the standard.
If this function were proposed as part of the Ada standard, that would
make sense. However, it is part of SAL, which often has a different
philosophy.
> I haven't used SAL, but these are the kind of comments you'd probably
> get from me if I did use this function. HTH.
Thanks for your comments.
--
-- Stephe