[squeak-dev] The Trunk: Compression-eem.41.mcz
commits at source.squeak.org
commits at source.squeak.org
Tue May 6 22:03:20 UTC 2014
Eliot Miranda uploaded a new version of Compression to project The Trunk:
http://source.squeak.org/trunk/Compression-eem.41.mcz
==================== Summary ====================
Name: Compression-eem.41
Author: eem
Time: 6 May 2014, 3:03:07.032 pm
UUID: 331a0bb5-cbf5-4a72-9b2b-f4a5ab92e6c2
Ancestors: Compression-fbs.40
Fix a bug in [Fast]InflateStream, thanks to Yoshiki Oshima:
This can be a nitpick of the year, but there is a bug in
InflateStream>>decompressBlock:with:
There is a part that reads (toward the end):
------------------------
collection
replaceFrom: readLimit+1
to: readLimit + length + 1
with: collection
startingAt: readLimit - distance + 1.
------------------------
but here we want to replace "length" bytes in collection, as opposed
to length + 1 bytes, so it has to say:
------------------------
collection
replaceFrom: readLimit+1
to: readLimit + length
with: collection
startingAt: readLimit - distance + 1.
------------------------
(So is the non-primitive version in FastInflateStream.)
The reason it does not matter is that replaceFrom:to:with:startingAt:
does not care about the source and destination being the same and
overlap between them. Even when the above bug puts one extra bytes in
collection temporarily, the extra byte will be wiped out in the next
iteration of the loop surrounding it. However, if you try to port
this to a language that does the "right thing" when there is an
overlap, it manifests as a bug.
-- Yoshiki
P.S.
It was a "rare" delight to point out a bug in Andreas' code^^; We miss
you.
=============== Diff against Compression-fbs.40 ===============
Item was changed:
----- Method: FastInflateStream>>decompressBlock:with: (in category 'inflating') -----
decompressBlock: llTable with: dTable
"Process the compressed data in the block.
llTable is the huffman table for literal/length codes
and dTable is the huffman table for distance codes."
| value extra length distance oldPos oldBits oldBitPos |
<primitive: 'primitiveInflateDecompressBlock' module: 'ZipPlugin'>
[readLimit < collection size and:[sourcePos <= sourceLimit]] whileTrue:[
"Back up stuff if we're running out of space"
oldBits := bitBuf.
oldBitPos := bitPos.
oldPos := sourcePos.
value := self decodeValueFrom: llTable.
value < 256 ifTrue:[ "A literal"
collection byteAt: (readLimit := readLimit + 1) put: value.
] ifFalse:["length/distance or end of block"
value = 256 ifTrue:["End of block"
state := state bitAnd: StateNoMoreData.
^self].
"Compute the actual length value (including possible extra bits)"
extra := (value bitShift: -16) - 1.
length := value bitAnd: 16rFFFF.
extra > 0 ifTrue:[length := length + (self nextBits: extra)].
"Compute the distance value"
value := self decodeValueFrom: dTable.
extra := (value bitShift: -16).
distance := value bitAnd: 16rFFFF.
extra > 0 ifTrue:[distance := distance + (self nextBits: extra)].
(readLimit + length >= collection size) ifTrue:[
bitBuf := oldBits.
bitPos := oldBitPos.
sourcePos := oldPos.
^self].
collection
replaceFrom: readLimit+1
+ to: readLimit + length
- to: readLimit + length + 1
with: collection
startingAt: readLimit - distance + 1.
readLimit := readLimit + length.
].
].!
Item was changed:
----- Method: InflateStream>>decompressBlock:with: (in category 'inflating') -----
decompressBlock: llTable with: dTable
"Process the compressed data in the block.
llTable is the huffman table for literal/length codes
and dTable is the huffman table for distance codes."
| value extra length distance oldPos oldBits oldBitPos |
[readLimit < collection size and:[sourcePos <= sourceLimit]] whileTrue:[
"Back up stuff if we're running out of space"
oldBits := bitBuf.
oldBitPos := bitPos.
oldPos := sourcePos.
value := self decodeValueFrom: llTable.
value < 256 ifTrue:[ "A literal"
collection byteAt: (readLimit := readLimit + 1) put: value.
] ifFalse:["length/distance or end of block"
value = 256 ifTrue:["End of block"
state := state bitAnd: StateNoMoreData.
^self].
"Compute the actual length value (including possible extra bits)"
extra := #(0 0 0 0 0 0 0 0 1 1 1 1 2 2 2 2 3 3 3 3 4 4 4 4 5 5 5 5 0) at: value - 256.
length := #(3 4 5 6 7 8 9 10 11 13 15 17 19 23 27 31 35 43 51 59 67 83 99 115 131 163 195 227 258) at: value - 256.
extra > 0 ifTrue:[length := length + (self nextBits: extra)].
"Compute the distance value"
value := self decodeValueFrom: dTable.
extra := #(0 0 0 0 1 1 2 2 3 3 4 4 5 5 6 6 7 7 8 8 9 9 10 10 11 11 12 12 13 13) at: value+1.
distance := #(1 2 3 4 5 7 9 13 17 25 33 49 65 97 129 193 257 385 513 769
1025 1537 2049 3073 4097 6145 8193 12289 16385 24577) at: value+1.
extra > 0 ifTrue:[distance := distance + (self nextBits: extra)].
(readLimit + length >= collection size) ifTrue:[
bitBuf := oldBits.
bitPos := oldBitPos.
sourcePos := oldPos.
^self].
collection
replaceFrom: readLimit+1
+ to: readLimit + length
- to: readLimit + length + 1
with: collection
startingAt: readLimit - distance + 1.
readLimit := readLimit + length.
].
].!
More information about the Squeak-dev
mailing list
|