comp.lang.ada
 help / color / mirror / Atom feed
From: Adam Beneschan <adam@irvine.com>
Subject: Re: Base64-Encoding
Date: Mon, 15 Oct 2007 11:24:16 -0700
Date: 2007-10-15T11:24:16-07:00	[thread overview]
Message-ID: <1192472656.757761.135150@z24g2000prh.googlegroups.com> (raw)
In-Reply-To: <20071015161229.3f439230@cube.tz.axivion.com>

On Oct 15, 7:12 am, Stefan Bellon <sbel...@sbellon.de> wrote:
> Hi all,
>
> I've been looking through the previous postings of the group and found
> two major threads where this topic has already been discussed. But the
> proposed solutions were all different to what I was thinking about. I
> have thought about the following:
>
> package body Base64 is
>
>    type Six_Bits is mod 2**6;
>    for Six_Bits'Size use 6;
>
>    type Six_Bits_Array is array (Natural range <>) of Six_Bits;
>    for Six_Bits_Array'Alignment use 1;  --  To overlay over String type.
>    for Six_Bits_Array'Component_Size use Six_Bits'Size;
>    pragma Pack (Six_Bits_Array);
>
>    Base64_Chars : constant array (Six_Bits) of Character :=
>      "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
>
>    function Encode
>      (Data : in String)
>      return String
>    is
>       Padded_Length : constant Natural := ((Data'Length + 2) / 3) * 3;
>       --  Pad input data to 3-Byte boundary.
>
>       Base64_Length : constant Natural := Padded_Length / 3 * 4;
>       --  Number of six-bit tokens necessary (including padding).
>
>       Six_Bits_Length : constant Natural := (Data'Length * 4 + 2) / 3;
>       --  Number of six-bit tokens necessary (without padding).
>
>       Padded_Data : String (1 .. Padded_Length) := (others => ASCII.NUL);
>       --  Padded input data.
>
>       Base64_Data : Six_Bits_Array (1 .. Base64_Length);
>       for Base64_Data'Address use Padded_Data'Address;
>       --  Overlay array of six-bit tokens over the padded input data.
>
>       Result : String (1 .. Base64_Length) := (others => '=');
>       --  Output buffer, initialized with '=' tokens for unfilled
>       --  end-markers.
>    begin
>       Padded_Data (1 .. Data'Length) := Data;
>       --  Initialize data into padded-data (can't be done with aggregate
>       --  in elaboration part, sadly).
>
>       --  Do the actual encoding ...
>       for I in 1 .. Six_Bits_Length loop
>          Result (I) := Base64_Chars (Base64_Data (I));
>       end loop;
>
>       return Result;
>    end Encode;
>
> end Base64;
>
> However it looks like this solution has a problem with endianness, in a
> way that the wrong 6 bits of the Bytes are used in the conversion.
>
> Is there an easy way to fix this (as I think the rest would be pretty
> neat) or is this way of trying to do it, doomed to fail anyway?

I vote for "doomed"---if your intent is to write portable code.  The
problem is that Ada doesn't give you enough control over the
representation of an array to solve the problem the way you'd like
to.  You're hoping for a representation of an array of 6-bit integers,
such that the first array element is contained in the upper 6 bits of
the first byte, the second array element is such that the two high
bits of the element are the lower 2 bits of the first byte and the
remaning four bits are the lower 4 bits of the second byte, etc.  I
don't think there's a way in Ada to specify an array representation
that precisely.  From what I can tell, if it's more convenient for an
implementation to store the first element in the low-order bits of the
*third* byte (let's say it can load three bytes as an integer
containing four array elements and then perform register shift
instructions to get the desired element), it is free to do so and
there's no Ada-defined pragma or representation clause to prevent it
from doing so.

If it were me, I'd just do the shifting and masking operations
myself.  You may be able to get somewhere by defining a record
containing four 6-bit integers and taking up three bytes, and using a
record representation clause to specify the exact locations of those
four integers.  You'd probably even be able to do this in a way that's
endianness-independent---I haven't tried it.  Of course, you'd have to
perform your operation on the four components of those records
separately; you can't put them into an array.

                     -- Adam




  parent reply	other threads:[~2007-10-15 18:24 UTC|newest]

Thread overview: 17+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2007-10-15 14:12 Base64-Encoding Stefan Bellon
2007-10-15 14:46 ` Base64-Encoding Jacob Sparre Andersen
2007-10-15 14:54   ` Base64-Encoding Stefan Bellon
2007-10-15 15:14     ` Base64-Encoding Jacob Sparre Andersen
2007-10-15 15:37       ` Base64-Encoding Robert A Duff
2007-10-15 15:40     ` Base64-Encoding Jean-Pierre Rosen
2007-10-15 16:39       ` Base64-Encoding Stefan Bellon
2007-10-16 10:42         ` Base64-Encoding Stephen Leake
2007-10-17 14:07           ` Base64-Encoding Stefan Bellon
2007-10-17 15:09             ` Base64-Encoding Adam Beneschan
2007-10-17 18:15               ` Base64-Encoding Larry Kilgallen
2007-10-15 18:24 ` Adam Beneschan [this message]
2007-10-19  2:43 ` Base64-Encoding anon
2007-10-19  4:33   ` Base64-Encoding anon
2007-10-19  7:35     ` Base64-Encoding Jean-Pierre Rosen
2007-10-19  6:59   ` Base64-Encoding Stefan Bellon
2007-10-19 19:40     ` Base64-Encoding anon
replies disabled

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