Re: Base64-Encoding
- From: Adam Beneschan <adam@xxxxxxxxxx>
- Date: Mon, 15 Oct 2007 11:24:16 -0700
On Oct 15, 7:12 am, Stefan Bellon <sbel...@xxxxxxxxxx> 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
.
- References:
- Base64-Encoding
- From: Stefan Bellon
- Base64-Encoding
- Prev by Date: Re: High-integrity networking
- Next by Date: Re: No networking in Florist?
- Previous by thread: Re: Base64-Encoding
- Next by thread: Re: Base64-Encoding
- Index(es):
Relevant Pages
|