eXept Software AG Logo

Smalltalk/X Webserver

Documentation of class 'Base64Coder':

Home

Documentation
www.exept.de
Everywhere
for:
[back]

Class: Base64Coder


Inheritance:

   Object
   |
   +--Visitor
      |
      +--AspectVisitor
         |
         +--ObjectCoder
            |
            +--BaseNCoder
               |
               +--Base64Coder
                  |
                  +--Base64UrlCoder

Package:
stx:libbasic2
Category:
System-Storage
Version:
rev: 1.41 date: 2023/05/28 10:27:06
user: cg
file: Base64Coder.st directory: libbasic2
module: stx stc-classLibrary: libbasic2

Description:


Instances of this class perform Base64 en- and decoding as defined in RFC 2045
3 bytes are mapped to 4 characters, representing 6 bits each.
The encoded string consists only of characters from the set:
    'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/='

Notice: for URLs, a slightly different encoding is used,
where instead of plus and slash, minus and underline are generated (see Base64UrlCoder).

The main entry point API is:
    Base64Coder encode:aStringOrBytes
and
    Base64Coder decode:aString

Typically, binary data is encoded as base64,
so the natural return value is a byte array.

If the decoder should return a string, use
    Base64Coder decodeAsString:aString.
otherwise, a bytearray is returned from the decode: method.



[instance variables:]

[class variables:]
    Base64Mapping         String   Mapping from bytes (with 6 valid bits)
                                   to Base64 characters
    Base64ReverseMapping  Array    Mapping from Base64 characters to 6-bit-Bytes

copyright

COPYRIGHT (c) 2002 by eXept Software AG All Rights Reserved This software is furnished under a license and may be used only in accordance with the terms of that license and with the inclusion of the above copyright notice. This software may not be provided or otherwise made available to, or used by, any other person. No title to or ownership of the software is hereby transferred.

Class protocol:

decoding
o  decode: aStringOrStream
because base64 decoding is used heavily in some protocols,
a specially tuned version is provided here
for the common case of decoding a string.
This returns a byteArray.

o  decodeAsString: encodedString
because base64 decoding is used heavily in some protocols,
a specially tuned version is provided here
for the common case of decoding a string.
This returns a string.

o  encode: aStringOrStream
because base64 encoding is used heavily in some protocols,
a specially tuned version is provided here
for the common case of encoding a string.
A string is generated with an inserted
newline after every 76 characters (see RFC 2045)

o  fastDecodeString: aString
because base64 decoding is used heavily in some protocols,
a specially tuned version is provided here
for the common case of decoding a string.
This returns a byteArray

Usage example(s):

     (Base64Coder encode:'queen%27s%20gambit') => 'cXVlZW4lMjdzJTIwZ2FtYml0'

     (Base64Coder decode:'cXVlZW4lMjdzJTIwZ2FtYml0') => #[113 117 101 101 110 37 50 55 115 37 50 48 103 97 109 98 105 116]
     (Base64Coder decode:'cXVlZW4lMjdzJTIwZ2FtYml0') asString => 'queen%27s%20gambit'
     (Base64Coder decodeAsString:'cXVlZW4lMjdzJTIwZ2FtYml0') => 'queen%27s%20gambit'

     (Base64Coder fastDecodeString:'cXVlZW4lMjdzJTIwZ2FtYml0') asString => 'queen%27s%20gambit'

o  fastDecodeString: aString asString: asStringBoolean
because base64 decoding is used heavily in some protocols,
a specially tuned version is provided here
for the common case of decoding a string.
If the argument is true, a string is returned; otherwise, a bytearray.
This is about 10 times faster than the regular decoder.

Usage example(s):

     (Base64Coder encode:'queen%27s%20gambit') => 'cXVlZW4lMjdzJTIwZ2FtYml0'

     (Base64Coder decode:'cXVlZW4lMjdzJTIwZ2FtYml0') asString => 'queen%27s%20gambit'
     (Base64Coder fastDecodeString:'cXVlZW4lMjdzJTIwZ2FtYml0') asString => 'queen%27s%20gambit'
     (Base64Coder fastDecodeString:'cXVlZW4lMjdzJTIwZ2FtYml0' asString:true) => 'queen%27s%20gambit'

     (Base64Coder encode:'a') => 'YQ=='
     (Base64Coder fastDecodeString:'YQ==' asString:true) => 'a'

     (Base64Coder encode:'aa') => 'YWE='
     (Base64Coder fastDecodeString:'YWE=' asString:true) => 'aa'

     |data encoded|
     data := ByteArray new:100000.
     encoded := Base64Coder encode:data.
     Time millisecondsToRun:[
        1000 timesRepeat:[
            Base64Coder decode:encoded.
        ]
     ]    

     |data encoded|
     data := ByteArray new:100000.
     encoded := Base64Coder encode:data.
     Time millisecondsToRun:[
        1000 timesRepeat:[
            Base64Coder fastDecodeString:encoded.
        ]
     ]   

o  fastEncode: aStringOrByteArray
because base64 encoding is used heavily in some protocols,
a specially tuned version is provided here
for the common case of encoding a string or bytearray.
A string is generated with an inserted
newline after every 76 characters (see RFC 2045)

o  fastEncode: aStringOrByteArray asString: asStringBoolean
because base64 encoding is used heavily in some protocols,
a specially tuned version is provided here,
for the common case of encoding a string or bytearray.
If asStringBoolean is true, a string is generated; otherwise, a bytearray is returned.
A newline is inserted after every 76 characters (see RFC 2045)

o  fastEncode: aStringOrByteArray asString: asStringBoolean lineLimit: lineLimitOrNil
because base64 encoding is used heavily in some protocols,
a specially tuned version is provided here
for the common case of encoding a string.
If asStringBoolean is true, a string is generated; otherwise, a bytearray is returned.
If lineLimitOrNil is non-nil, a newline is inserted after every such number of characters

Usage example(s):

     (Base64Coder encode:'queen%27s%20gambit') => 'cXVlZW4lMjdzJTIwZ2FtYml0'
     (Base64Coder fastEncode:'queen%27s%20gambit' asString:true) => 'cXVlZW4lMjdzJTIwZ2FtYml0'

     (Base64Coder decode:'cXVlZW4lMjdzJTIwZ2FtYml0') asString => 'queen%27s%20gambit'
     (Base64Coder fastDecodeString:'cXVlZW4lMjdzJTIwZ2FtYml0') asString => 'queen%27s%20gambit'
     (Base64Coder fastDecodeString:'cXVlZW4lMjdzJTIwZ2FtYml0' asString:true) => 'queen%27s%20gambit'

     (Base64Coder encode:'a') => 'YQ=='
     (Base64Coder fastEncode:'a' asString:true) => 'YQ=='
     (Base64Coder fastDecodeString:'YQ==' asString:true) => 'a'

     (Base64Coder encode:'aa') => 'YWE='
     (Base64Coder fastEncode:'aa' asString:true) => 'YWE='
     (Base64Coder fastDecodeString:'YWE=' asString:true) => 'aa'

     |data|
     data := ByteArray new:1000.
     Time millisecondsToRun:[
        10000 timesRepeat:[self halt.
            Base64Coder encode:data.
        ]
     ]

     |data|
     data := ByteArray new:1000.
     Base64Coder fastEncode:data asString:true lineLimit:20.

     |data|
     data := ByteArray new:1000.
     Base64Coder fastEncode:data asString:true lineLimit:nil.

     |data|
     data := ByteArray new:1000.
     Time millisecondsToRun:[
        10000 timesRepeat:[
            Base64Coder fastEncode:data.
        ]
     ]

     self assert:((Base64Coder fastEncode:'abc' asString:true)
                  = 'abc' base64Encoded).
     self assert:((Base64Coder fastEncode:'a' asString:true)
                  = 'a' base64Encoded).
     self assert:((Base64Coder fastEncode:'ab' asString:true)
                  = 'ab' base64Encoded).
     self assert:((Base64Coder fastEncode:'abcd' asString:true)
                  = 'abcd' base64Encoded).
     self assert:((Base64Coder fastEncode:'abcde' asString:true)
                  = 'abcde' base64Encoded).
     self assert:((Base64Coder fastEncode:'abcdef' asString:true)
                  = 'abcdef' base64Encoded).

     self assert:((Base64Coder fastEncode:#'parseMethod:onError:rememberNodes:nodeGenerationCallback:' asString:true)
                  = #'parseMethod:onError:rememberNodes:nodeGenerationCallback:' base64Encoded).

     self assert:((Base64Coder fastEncode:'_INVOKESTATIC_R:' asString:true)
                  = '_INVOKESTATIC_R:' base64Encoded).

     self assert:((Base64Coder fastEncode:#'_INVOKESTATIC_R:' asString:true)
                  = #'_INVOKESTATIC_R:' base64Encoded)

     self assert:((Base64Coder fastEncode:'_INVOKESTATIC_R:' asString:true)
                  = (Base64Coder fastEncode:#'_INVOKESTATIC_R:' asString:true)).

     self assert:((#'_INVOKESTATIC_R:' base64Encoded)
                  = ('_INVOKESTATIC_R:' base64Encoded)).



     self assert:((Base64Coder fastEncode:'_INVOKESTATIC_R:_:' asString:true)
                  = '_INVOKESTATIC_R:_:' base64Encoded).

     self assert:((Base64Coder fastEncode:#'_INVOKESTATIC_R:_:' asString:true)
                  = #'_INVOKESTATIC_R:_:' base64Encoded)

     self assert:((Base64Coder fastEncode:'_INVOKESTATIC_R:_:' asString:true)
                  = (Base64Coder fastEncode:#'_INVOKESTATIC_R:_:' asString:true)).

     self assert:((#'_INVOKESTATIC_R:_:' base64Encoded)
                  = ('_INVOKESTATIC_R:_:' base64Encoded)).

     Symbol allInstancesDo:[:each |
         self assert:((Base64Coder fastEncode:each asString:true)
                     =  (Base64Coder encode:each with:nil))
     ]

initialization
o  initializeMappings
initialize class variables

Usage example(s):

     Base64Mapping := nil.
     self initializeMappings

o  mapping

o  reverseMapping


Instance protocol:

encoding
o  nextPutByte: aByte
encode aByte on the output stream

misc
o  flush
flush the remaining bits of buffer.
The number of bits in buffer is not a multiple of 6, so we pad
the buffer and signal that padding has been done via $= characters.

private
o  fillBuffer
fill buffer with next 4 characters each representing 6 bits.
Used when decoding.


Examples:


   (Base64Coder encode:'queen%27s%20gambit') asString = 'cXVlZW4lMjdzJTIwZ2FtYml0'
   (Base64Coder decode:'cXVlZW4lMjdzJTIwZ2FtYml0') asString = 'queen%27s%20gambit'
   |data1 text data2|

   data1 := #[0 1 16r7F 16r80 16r81 16rFE 16rFF].
   text := Base64Coder encode:data1.
   data2 := Base64Coder decode:text.
   data2
   |coder|

   coder := Base64Coder on:'' writeStream.
   coder nextPutAll:#[0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19].
   coder flush.
   coder contents inspect.
   coder reset.
   coder nextPut:254.
   coder contents inspect.
   |coder decoder|

   coder := Base64Coder on:'' writeStream.
   coder nextPutAll:#[0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20].
   coder flush.

   decoder := Base64Coder on:(coder contents readStream).
   [decoder atEnd] whileFalse:[
      Transcript show:decoder next
   ].
   Transcript cr.
   |coder|

   coder := Base64Coder on:'' writeStream.
   coder nextPutAll:(0 to:200) asByteArray.
   coder flush.

   Transcript showCR:(coder contents).
   |bytes|

   bytes := ByteArray new:100000.
   Time millisecondsToRun:[
       100 timesRepeat:[
           Base64Coder encode:bytes.
       ].
   ].
   |bytes encoded decoded|

   bytes := #[0 0 0] copy.
   0 to:255 do:[:b1 |
       Transcript showCR:b1.
       bytes at:1 put:b1.
       0 to:255 do:[:b2 |
           bytes at:2 put:b2.
           0 to:255 do:[:b3 |
               bytes at:3 put:b3.
               encoded := Base64Coder encode:bytes.
               decoded := Base64Coder decode:encoded.
               self assert:(decoded = bytes).
           ]
       ]
   ].


ST/X 7.7.0.0; WebServer 1.702 at 20f6060372b9.unknown:8081; Thu, 05 Dec 2024 02:42:08 GMT