Tobias Pape uploaded a new version of Collections to project The Trunk:
http://source.squeak.org/trunk/Collections-topa.701.mcz ==================== Summary ==================== Name: Collections-topa.701 Author: topa Time: 10 July 2016, 9:00:58.083099 pm UUID: 5ae1b44b-94ef-4657-a76e-387509401f08 Ancestors: Collections-eem.700 Add an Ascii85 converter akin to Base64MimeConverter =============== Diff against Collections-eem.700 =============== Item was added: + Object subclass: #Ascii85Converter + instanceVariableNames: 'dataStream stringStream number85 tupleSize binary' + classVariableNames: '' + poolDictionaries: '' + category: 'Collections-Streams'! + + !Ascii85Converter commentStamp: 'topa 7/10/2016 20:57' prior: 0! + I convert between binary data and an Ascii85 text representation of PostScript and PDF fame. + I am a little bit more efficient (~25% overhead) than Base64 (~30% overhead). + + Instance Variables + binary: <Boolean> - Tells whether to decode to binary data or characters + dataStream: <PositionableStream> - The data stream to decode to or encode from (Typically does not contain Ascii85) + stringStream: <PositionableStream> - The text stream to decode from or encode to (Always contains Ascii85) + number85: <Integer> - Decoder state, accumulated read number in base85 + tupleSize: <SmallInteger> - Number of bytes read into number85 already + + 'Hello, World' ascii85Encoded. + + '<~87cURD]htuF_+us~>' ascii85Decoded. + ! Item was added: + ----- Method: Ascii85Converter class>>decode:as: (in category 'convenience') ----- + decode: aStringOrStream as: contentsClass + + ^ contentsClass streamContents: + [:out | self decode: aStringOrStream to: out]! Item was added: + ----- Method: Ascii85Converter class>>decode:to: (in category 'convenience') ----- + decode: aStringOrStream to: outStream + + ^ (self stringStream: aStringOrStream readStream dataStream: outStream) + decode! Item was added: + ----- Method: Ascii85Converter class>>decodeToBytes: (in category 'convenience') ----- + decodeToBytes: aStringOrStream + " Analogous to Base64MimeConverter>>#mimeDecodeToBytes:" + | expectedSize | + expectedSize := aStringOrStream size * 4 // 5. + ^ (ByteArray new: expectedSize streamContents: + [:stream | + (self stringStream: aStringOrStream readStream dataStream: stream) + decodeToByteArray]) readStream! Item was added: + ----- Method: Ascii85Converter class>>decodeToChars: (in category 'convenience') ----- + decodeToChars: aStringOrStream + " Analogous to Base64MimeConverter>>#mimeDecodeToChars:" + | expectedSize | + expectedSize := aStringOrStream size * 4 // 5. + ^ (String new: expectedSize streamContents: + [:stream | self decode: aStringOrStream to: stream]) readStream! Item was added: + ----- Method: Ascii85Converter class>>encode: (in category 'convenience') ----- + encode: aCollectionOrStream + + ^ String streamContents: + [:out | self encode: aCollectionOrStream to: out]! Item was added: + ----- Method: Ascii85Converter class>>encode:to: (in category 'convenience') ----- + encode: aCollectionOrStream to: outStream + + ^ (self stringStream: outStream dataStream: aCollectionOrStream readStream) + encode! Item was added: + ----- Method: Ascii85Converter class>>stringStream:dataStream: (in category 'instance creation') ----- + stringStream: aStream dataStream: anotherStream + + ^ self new + stringStream: aStream; + dataStream: anotherStream; + yourself! Item was added: + ----- Method: Ascii85Converter>>ascii (in category 'accessing') ----- + ascii + + binary := false.! Item was added: + ----- Method: Ascii85Converter>>binary (in category 'accessing') ----- + binary + + binary := true.! Item was added: + ----- Method: Ascii85Converter>>dataStream (in category 'accessing') ----- + dataStream + + ^dataStream! Item was added: + ----- Method: Ascii85Converter>>dataStream: (in category 'accessing') ----- + dataStream: anObject + + dataStream := anObject.! Item was added: + ----- Method: Ascii85Converter>>decode (in category 'conversion') ----- + decode + + self readBOD ifFalse: [^ self dataStream]. + + [self stringStream atEnd] whileFalse: [ + self stringStream skipSeparators. + self readEOD ifTrue: [^ self endDecode]. "<--- End of data" + + self decodeChar: self stringStream next ifFail: [^ self dataStream]]. + "actually, should not reach, but our failure condition is returning the stream, anyway" + ^ self dataStream! Item was added: + ----- Method: Ascii85Converter>>decodeChar:ifFail: (in category 'conversion') ----- + decodeChar: char ifFail: failBlock + + char = $z ifTrue: [^ self decodeZIfFail: failBlock]. + + (char between: $!! and: $u) ifFalse: [^ failBlock value]. + + self incrementTupleSize. + self incrementNumber85: char asInteger - 33 * (self pow85 at: self tupleSize). + self tupleSize = 5 ifTrue: + [self isBinary + ifTrue: [self writeBytes255: self number85 atMax: 4] + ifFalse: [self writeChars255: self number85 atMax: 4]. + self resetDecoderState]! Item was added: + ----- Method: Ascii85Converter>>decodeToByteArray (in category 'conversion') ----- + decodeToByteArray + + self binary. + ^ self decode! Item was added: + ----- Method: Ascii85Converter>>decodeZIfFail: (in category 'conversion') ----- + decodeZIfFail: failBlock + + self tupleSize ~= 0 ifTrue: [^ failBlock value]. + self dataStream next: 4 put: (self isBinary ifTrue: [0] ifFalse: [Character null]). + ! Item was added: + ----- Method: Ascii85Converter>>encode (in category 'conversion') ----- + encode + + | lineLength | + + lineLength := 0. + self stringStream nextPutAll: '<~'. + [self dataStream atEnd] whileFalse: [ + | raw data out | + lineLength >= 74 ifTrue: [self stringStream cr. lineLength := 0]. + out := 5. + raw := (self dataStream next: 4) asByteArray. + raw size < 4 ifTrue: + [out := raw size + 1. + raw := raw, (self padOfSize: 4 - raw size)]. + data := raw unsignedLongAt: 1 bigEndian: true. + data = 0 + ifTrue: [self stringStream nextPut: $z. lineLength := lineLength + 1] + ifFalse: [self write85: data atMax: out. lineLength := lineLength + out]]. + self stringStream nextPutAll: '~>'. + ^ self stringStream + ! Item was added: + ----- Method: Ascii85Converter>>endDecode (in category 'private') ----- + endDecode + + self tupleSize > 0 ifTrue: + [self incrementNumber85: (self pow85 at: self tupleSize). + self isBinary + ifTrue: [self writeBytes255: self number85 atMax: self tupleSize - 1] + ifFalse: [self writeChars255: self number85 atMax: self tupleSize - 1]]. + ^ self dataStream! Item was added: + ----- Method: Ascii85Converter>>incrementNumber85: (in category 'private') ----- + incrementNumber85: aNumber + + number85 := number85 + aNumber. + + ! Item was added: + ----- Method: Ascii85Converter>>incrementTupleSize (in category 'private') ----- + incrementTupleSize + + tupleSize := tupleSize + 1. + ! Item was added: + ----- Method: Ascii85Converter>>initialize (in category 'initialize-release') ----- + initialize + + super initialize. + self ascii. + self resetDecoderState.! Item was added: + ----- Method: Ascii85Converter>>isBinary (in category 'testing') ----- + isBinary + + ^ binary! Item was added: + ----- Method: Ascii85Converter>>number85 (in category 'accessing') ----- + number85 + + ^ number85! Item was added: + ----- Method: Ascii85Converter>>padOfSize: (in category 'private') ----- + padOfSize: aNumber + + aNumber = 1 ifTrue: [^ #(0)]. + aNumber = 2 ifTrue: [^ #(0 0)]. + aNumber = 3 ifTrue: [^ #(0 0 0)]. + self error: 'Should not reach'.! Item was added: + ----- Method: Ascii85Converter>>pow85 (in category 'private') ----- + pow85 + + ^ #(52200625 614125 7225 85 1) "{85*85*85*85 . 85*85*85 . 85*85 . 85. 1}"! Item was added: + ----- Method: Ascii85Converter>>readBOD (in category 'private') ----- + readBOD + + self stringStream skipSeparators. + self stringStream peek = $< ifFalse: [^ false] ifTrue: + [self stringStream next. "ignore" + self stringStream peek = $~ ifFalse: [^ false] ifTrue: + [self stringStream next "ignore"]]. + ^ true! Item was added: + ----- Method: Ascii85Converter>>readEOD (in category 'private') ----- + readEOD + + self stringStream skipSeparators. + self stringStream peek = $~ ifFalse: [^ false] ifTrue: + [self stringStream next. "ignore" + self stringStream peek = $> ifFalse: [^ false] ifTrue: + [self stringStream next "ignore"]]. + ^ true! Item was added: + ----- Method: Ascii85Converter>>resetDecoderState (in category 'private') ----- + resetDecoderState + + number85 := 0. + tupleSize := 0. + ! Item was added: + ----- Method: Ascii85Converter>>stringStream (in category 'accessing') ----- + stringStream + + ^ stringStream! Item was added: + ----- Method: Ascii85Converter>>stringStream: (in category 'accessing') ----- + stringStream: anObject + + stringStream := anObject.! Item was added: + ----- Method: Ascii85Converter>>tupleSize (in category 'accessing') ----- + tupleSize + + ^ tupleSize! Item was added: + ----- Method: Ascii85Converter>>write85:atMax: (in category 'writing') ----- + write85: anInteger atMax: aNumber + + | c1 c2 c3 c4 c5 remain | + remain := anInteger. + c5 := (remain \\ 85 + 33) asCharacter. remain := remain // 85. + c4 := (remain \\ 85 + 33) asCharacter. remain := remain // 85. + c3 := (remain \\ 85 + 33) asCharacter. remain := remain // 85. + c2 := (remain \\ 85 + 33) asCharacter. remain := remain // 85. + c1 := (remain \\ 85 + 33) asCharacter. remain := remain // 85. + aNumber > 0 ifTrue: [self stringStream nextPut: c1. + aNumber > 1 ifTrue: [self stringStream nextPut: c2. + aNumber > 2 ifTrue: [self stringStream nextPut: c3. + aNumber > 3 ifTrue: [self stringStream nextPut: c4. + aNumber > 4 ifTrue: [self stringStream nextPut: c5]]]]]. + ! Item was added: + ----- Method: Ascii85Converter>>writeBytes255:atMax: (in category 'writing') ----- + writeBytes255: anInteger atMax: aNumber + + (aNumber between: 1 and: 4) ifFalse: [^ self error: 'Unexpected byte count']. + 4 to: (5 - aNumber) by: -1 do: + [:index | self dataStream nextPut: (anInteger digitAt: index)]. + ! Item was added: + ----- Method: Ascii85Converter>>writeChars255:atMax: (in category 'writing') ----- + writeChars255: anInteger atMax: aNumber + + (aNumber between: 1 and: 4) ifFalse: [^ self error: 'Unexpected byte count']. + 4 to: (5 - aNumber) by: -1 do: + [:index | self dataStream nextPut: (anInteger digitAt: index) asCharacter]. + ! Item was added: + ----- Method: ByteArray>>ascii85Encoded (in category 'converting') ----- + ascii85Encoded + "Encode the receiver as Ascii85" + "'Hello World' asByteArray ascii85Encoded" + + ^ (Ascii85Converter encode: self readStream) contents! Item was added: + ----- Method: String>>ascii85Decoded (in category 'converting') ----- + ascii85Decoded + "Decode the receiver from Ascii85" + "'<~87cURD]i,""Ebo7~>' ascii85Decoded" + + ^ self ascii85DecodedAs: self class + ! Item was added: + ----- Method: String>>ascii85DecodedAs: (in category 'converting') ----- + ascii85DecodedAs: aClass + "Decode the receiver from Ascii85" + "'<~87cURD]i,""Ebo7~>' ascii85DecodedAs: String" + + ^ Ascii85Converter decode: self as: aClass! Item was added: + ----- Method: String>>ascii85Encoded (in category 'converting') ----- + ascii85Encoded + "Encode the receiver as Ascii85" + "'Hello World' ascii85Encoded" + + ^ (Ascii85Converter encode: self readStream) contents + ! |
Free forum by Nabble | Edit this page |