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=-0.3 required=5.0 tests=BAYES_00, REPLYTO_WITHOUT_TO_CC autolearn=no autolearn_force=no version=3.4.4 X-Google-Thread: 103376,e710f7d3f890e76b X-Google-Attributes: gid103376,public,usenet X-Google-Language: ENGLISH,ASCII-7-bit Path: g2news2.google.com!news1.google.com!border1.nntp.dca.giganews.com!nntp.giganews.com!wn13feed!worldnet.att.net!bgtnsc05-news.ops.worldnet.att.net.POSTED!53ab2750!not-for-mail Newsgroups: comp.lang.ada From: anon@anon.org (anon) Subject: Re: Base64-Encoding Reply-To: anon@anon.org (anon) References: <20071015161229.3f439230@cube.tz.axivion.com> <20071019085934.7c1a525f@cube.tz.axivion.com> X-Newsreader: IBM NewsReader/2 2.0 Message-ID: Date: Fri, 19 Oct 2007 19:40:56 GMT NNTP-Posting-Host: 12.65.30.234 X-Complaints-To: abuse@worldnet.att.net X-Trace: bgtnsc05-news.ops.worldnet.att.net 1192822856 12.65.30.234 (Fri, 19 Oct 2007 19:40:56 GMT) NNTP-Posting-Date: Fri, 19 Oct 2007 19:40:56 GMT Organization: AT&T Worldnet Xref: g2news2.google.com comp.lang.ada:2505 Date: 2007-10-19T19:40:56+00:00 List-Id: 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 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