comp.lang.ada
 help / color / mirror / Atom feed
From: anon@anon.org (anon)
Subject: Re: Base64-Encoding
Date: Fri, 19 Oct 2007 19:40:56 GMT
Date: 2007-10-19T19:40:56+00:00	[thread overview]
Message-ID: <cL7Si.240401$ax1.92228@bgtnsc05-news.ops.worldnet.att.net> (raw)
In-Reply-To: 20071019085934.7c1a525f@cube.tz.axivion.com

In my last post I answer about ENDIAN.

Now for two algorithms to convert data to Base64:

-- --------------------------------------------------------
-- Base64.ads
--

--
-- For conversion -- The use of a 4 byte array is faster since the CPUs 
--                   of today normally use 8-bits (quarter word) and 
--                   actually have quarter word storage instructions.
--                   
--
--                   The usage of packed record requires extra 
--                   code to be added to perform the record packing
--                   which will require more cpu cycles.
--
--                   Exception would be if your working on a older 
--                   system like the 1108 9-bit "Univac" (now called 
--                   "Unisys" ) of the 1970s which had 3-bits, 6-bits
--                   and 9-bits access instructions.
--

package Base64 is

-- -------------------------- --
-- TYPE: Base 64 Basics Types --
-- -------------------------- --

  --
  -- build the 6 bit 
  --
  type Bit_6 is mod 2 ** 6 ; 


  --
  -- Base_64 String Array 
  --
  type Base64_String is new String ( 1..4 ) ;


-- --------------------------------------- --
-- TYPE: Base 64 Basics using 4 byte array --
-- --------------------------------------- --

  --
  -- packed Bit_6 into 4 bytes
  --
  type Base64_Array is array ( 0 .. 3 ) of Bit_6 ;


-- ----------------------------------------- --
-- TYPE: Base 64 Basics using 3 byte records --
-- ----------------------------------------- --


  --
  -- packed Bit_6 into 3 bytes
  --
-- ------------------------------ --
-- TYPE: Base 64 Conversion Types --
-- ------------------------------ --

  --
  -- Base_64_Descriptor is used in converting 8 bit 
  -- characters to 6 bits ;
  --
  type Base_64_Descriptor is record
                               Value_3  : Bit_6 ;
                               Value_2  : Bit_6 ;
                               Value_1  : Bit_6 ;
                               Value_0  : Bit_6 ;
                             end record ;  
  --
  -- insure 3 byte usage for Character_Descriptor ;
  --
  pragma pack ( Base_64_Descriptor ) ; 




-- ------------------------------- --
-- TYPE: Data Conversion Functions --
-- ------------------------------- --

  --
  -- 4 byte version
  --
  function Coding ( B_String : Base64_String ) 
             return Base64_Array ;

  function Coding ( B_Array : Base64_Array ) 
             return Base64_String ;


  --
  -- 3 byte version
  --
  function Coding ( B_String : Base64_String ) 
             return Base_64_Descriptor ;

  function Coding ( B_Array : Base_64_Descriptor ) 
             return Base64_String ;

  --
  -- Obtain conversion character
  --
  function Base64_Character ( C : Character ) return Character ;


end Base64 ;

-- --------------------------------------------------------
-- Base64.adb
--
with Interfaces ;
use  Interfaces ;

with Ada.Unchecked_Conversion ;


package body Base64 is


  --
  -- Base_64 Character Set ;
  --
  Characters : array ( Character range ASCII.Nul .. '?' ) of 
                 Character := 
                         "ABCDEFGHIJKLMNOPQRSTUVWXYZ" & 
                         "abcdefghijklmnopqrstuvwxyz" & 
                         "0123456789+/" ;

-- ------------------------------ --
-- TYPE: Base 64 Conversion Types --
-- ------------------------------ --

  --
  -- Character_Descriptor is used in converting 8 bit 
  -- characters to 6 bits ;
  --
  type Character_Descriptor is record
                            unused : Unsigned_8 range 0..3 ;
                            Value  : Bit_6 ;
                          end record ;
  --
  -- set bit order
  --
  for Character_Descriptor use record
                            unused at 0 range 6..7 ;
                            Value  at 0 range 0..5 ;
                          end record ;
  --
  -- insure 1 byte usage for Character_Descriptor ;
  --
  pragma pack ( Character_Descriptor ) ; 


-- ------------------------------- --
-- TYPE: Data Conversion Functions --
-- ------------------------------- --

    function Char_8_To_Char_6 is new Ada.Unchecked_Conversion 
                             ( Character, Character_Descriptor ) ;

    function Char_6_To_Char_8  is new Ada.Unchecked_Conversion 
                             ( Character_Descriptor, Character ) ;


  -- -------------- --
  -- 4 byte version --
  -- -------------- --

  function Coding ( B_String : Base64_String ) return Base64_Array is

      Temp : Base64_Array ;
      Work : Character_Descriptor ;

    begin -- Coding

      Work := Char_8_To_Char_6 ( B_String ( 4 ) ) ;
      Temp ( 3 ) := Work.Value ;

      Work := Char_8_To_Char_6 ( B_String ( 3 ) ) ;
      Temp ( 2 ) := Work.Value ;

      Work := Char_8_To_Char_6 ( B_String ( 2 ) ) ;
      Temp ( 1 ) := Work.Value ;

      Work := Char_8_To_Char_6 ( B_String ( 1 ) ) ;
      Temp ( 0 ) := Work.Value ;

      return Temp ;
    end Coding ;       


  function Coding ( B_Array : Base64_Array ) return Base64_String  is

      Temp : Base64_String ;
      Work : Character_Descriptor ;

    begin -- Coding
      Work.unused := 0 ; -- to insure value of conversion ;

      Work.Value := B_Array ( 3 ) ;
      Temp ( 4 ) := Char_6_To_Char_8 ( Work ) ;

      Work.Value := B_Array ( 2 ) ;
      Temp ( 3 ) := Char_6_To_Char_8 ( Work ) ;

      Work.Value := B_Array ( 1 ) ;
      Temp ( 2 ) := Char_6_To_Char_8 ( Work ) ;

      Work.Value := B_Array ( 0 ) ;
      Temp ( 1 ) := Char_6_To_Char_8 ( Work ) ;

      return Temp ;
    end Coding ;       


  -- -------------- --
  -- 3 byte version --
  -- -------------- --

  function Coding ( B_String : Base64_String ) 
             return Base_64_Descriptor is

      Temp : Base_64_Descriptor ;
      Work : Character_Descriptor ;

    begin -- Coding
      Work := Char_8_To_Char_6 ( B_String ( 4 ) ) ;
      Temp.Value_3 := Work.Value ;

      Work := Char_8_To_Char_6 ( B_String ( 3 ) ) ;
      Temp.Value_2 := Work.Value ;

      Work := Char_8_To_Char_6 ( B_String ( 2 ) ) ;
      Temp.Value_1 := Work.Value ;

      Work := Char_8_To_Char_6 ( B_String ( 1 ) ) ;
      Temp.Value_0 := Work.Value ;

      return Temp ;
    end Coding ;       


  function Coding ( B_Array : Base_64_Descriptor ) 
             return Base64_String is

      Temp : Base64_String ;
      Work : Character_Descriptor ;

    begin -- Coding
      Work.unused := 0 ; -- to insure value of conversion ;

      Work.Value := B_Array.Value_3 ;
      Temp ( 4 ) := Char_6_To_Char_8 ( Work ) ;

      Work.Value := B_Array.Value_2 ;
      Temp ( 3 ) := Char_6_To_Char_8 ( Work ) ;

      Work.Value := B_Array.Value_1 ;
      Temp ( 2 ) := Char_6_To_Char_8 ( Work ) ;

      Work.Value := B_Array.Value_0 ;
      Temp ( 1 ) := Char_6_To_Char_8 ( Work ) ;

      return Temp ;
    end Coding ;       



  --
  -- Obtain conversion 8-bit character
  --
  function Base64_Character ( C : Character ) return Character is
    begin  -- Base64_Character
      return Characters ( C ) ;
    end Base64_Character ;

end Base64 ;

-- --------------------------------------------------------
-- Test64.adb -- Test program
--

with Base64 ; 


with Ada.Text_IO ;
with Ada.Integer_Text_IO ;

use  Ada.Text_IO ;
use  Ada.Integer_Text_IO ;


procedure test64 is

  a : Base64.Base64_String := "1234";
  b : Base64.Base_64_Descriptor ;
  c : Base64.base_64_Descriptor := ( 10, 20, 30, 40 ) ;

  d : Base64.base64_Array := ( 00, 01, 02, 03 ) ;
  e : Base64.Base64_String ;
  f : Base64.base64_Array ;

begin

  --
  -- Test using 4 byte array
  --

  Put ( d'size ) ;
  New_Line ;
  Put ( e'size ) ;
  New_Line ;

  e := Base64.Coding ( d ) ;
  f := Base64.Coding ( e ) ;

  Put ( "Data : " ) ;
  Put ( Base64.Base64_Character ( e ( 1 ) ) ) ;
  Put ( Base64.Base64_Character ( e ( 2 ) ) ) ;
  Put ( Base64.Base64_Character ( e ( 3 ) ) ) ;
  Put ( Base64.Base64_Character ( e ( 4 ) ) ) ;
  New_Line ;


  b := Base64.Coding ( a ) ;

  Put ( a'size ) ;
  New_Line ;
  Put ( b'size ) ;  -- 24 aka 3 byte pack record
  New_Line ;


  --
  -- Test using packed 3 byte record
  --
  a := Base64.Coding ( c ) ;

  Put ( "Data : " ) ;
  Put ( Base64.Base64_Character ( a ( 1 ) ) ) ;
  Put ( Base64.Base64_Character ( a ( 2 ) ) ) ;
  Put ( Base64.Base64_Character ( a ( 3 ) ) ) ;
  Put ( Base64.Base64_Character ( a ( 4 ) ) ) ;
  New_Line ;
 

end Test64 ;


In <20071019085934.7c1a525f@cube.tz.axivion.com>, Stefan Bellon <sbellon@sbellon.de> writes:
>On Fr, 19 Okt, anon wrote:
>
>>   function To_Base64 is new Ada.Unchecked_Conversion 
>>                              ( Source => Unsigned_8, 
>>                                Target => base64_descriptor ) ;
>> 
>>   function From_Base64 is new Ada.Unchecked_Conversion 
>>                              ( Target => Unsigned_8, 
>>                                Source => base64_descriptor ) ;
>
>But this only converts one whole byte (aka Unsigned_8) into a Six_Bits
>by ignoring the two top-bits. This does not help with my original idea
>of overlaying a packed array of 6-bit elements over an array of 8-bit
>characters and then looping over the 6-bit elements to do the
>conversion in a simple loop, character by character.
>
>> In 2001 Tom Moran created a Ada BASE64 package which is archived at 
>> 
>> http://www.adapower.com/index.php?Command=Class&ClassID=Algorithms&CID=257
>> 
>> have a look at it. I a quick look it kind of suggest that the endian
>> for Six_Bits is not important.
>
>Yes, I know this package. But it handles three bytes in the original in
>one go and always encodes three bytes into four 6-bits.
>
>As I mentioned in my first posting, I am aware of the solutions to do
>the actual conversion that exist (and already have been discussed a
>few times here in the group). I was just wondering whether my idea
>of overlaying the two arrays could be easily "fixed" so that it works.
>
>But thanks for your ideas!
>
>-- 
>Stefan Bellon




      reply	other threads:[~2007-10-19 19:40 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 ` Base64-Encoding Adam Beneschan
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     ` anon [this message]
replies disabled

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