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.37 date: 2019/03/23 20:49:56
user: cg
file: Base64Coder.st directory: libbasic2
module: stx stc-classLibrary: libbasic2
Author:
Stefan Vogel

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


Related information:

    RFC
    [ttps]

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

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:[
	10 timesRepeat:[
	    Base64Coder decode:encoded.
	]
     ]

     |data encoded|
     data := ByteArray new:100000.
     encoded := Base64Coder encode:data.
     Time millisecondsToRun:[
	10 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.2.0.0; WebServer 1.670 at bd0aa1f87cdd.unknown:8081; Thu, 28 Mar 2024 12:27:33 GMT