[squeak-dev] The Trunk: Collections-topa.701.mcz

commits at source.squeak.org commits at source.squeak.org
Sun Jul 10 19:01:16 UTC 2016


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
+ !



More information about the Squeak-dev mailing list