[squeak-dev] The Inbox: Multilingual-pre.238.mcz
commits at source.squeak.org
commits at source.squeak.org
Sat May 26 08:02:20 UTC 2018
Patrick Rein uploaded a new version of Multilingual to project The Inbox:
http://source.squeak.org/inbox/Multilingual-pre.238.mcz
==================== Summary ====================
Name: Multilingual-pre.238
Author: pre
Time: 26 May 2018, 10:01:56.809551 am
UUID: 3f43777d-957b-374e-8bc6-2254763879f5
Ancestors: Multilingual-nice.237
Fixes the failing UTF-16 bug due to a missing initialization of the latin1 map.
Also adds validation for overlong sequences in UTF-8. Refactors some of the UTF-8 conversion code to make the bitmasks more obvious. The performance hit from the validation seems to be negligible but further testing is required.
=============== Diff against Multilingual-nice.237 ===============
Item was changed:
----- Method: ByteTextConverter class>>initialize (in category 'class initialization') -----
initialize
self == ByteTextConverter
ifTrue: [self allSubclassesDo: [:c | c initialize]]
+ ifFalse: [self
- ifFalse: [self
initializeDecodeTable;
initializeEncodeTable;
initializeLatin1MapAndEncodings]
!
Item was added:
+ ----- Method: UTF16TextConverter class>>initializeLatin1MapAndEncodings (in category 'utilities') -----
+ initializeLatin1MapAndEncodings
+ "Initialize the latin1Map and latin1Encodings.
+ These variables ensure that conversions from latin1 ByteString is reasonably fast"
+
+ latin1Map := (ByteArray new: 256) atAllPut: 1.
+ latin1Encodings := (0 to: 255) collect: [:i | (ByteArray newFrom: {0 . i}) asString]!
Item was changed:
----- Method: UTF8TextConverter class>>decodeByteString: (in category 'conversion') -----
decodeByteString: aByteString
"Convert the given string from UTF-8 using the fast path if converting to Latin-1"
+ | outStream lastIndex nextIndex limit byte1 byte2 byte3 byte4 unicode continuationByteMask |
- | outStream lastIndex nextIndex limit byte1 byte2 byte3 byte4 unicode |
lastIndex := 1.
(nextIndex := ByteString findFirstInString: aByteString inSet: latin1Map startingAt: lastIndex) = 0
ifTrue: [ ^aByteString ].
limit := aByteString size.
outStream := (String new: limit) writeStream.
+ continuationByteMask := 2r00111111.
[
outStream next: nextIndex - lastIndex putAll: aByteString startingAt: lastIndex.
byte1 := aByteString byteAt: nextIndex.
+
+ "The byte range checks are separated into single checks to allow for implementing recovery --pre
+ For the rules see: http://www.unicode.org/versions/Unicode7.0.0/UnicodeStandard-7.0.pdf page 125 table 3-7"
+ (byte1 bitAnd: 2r11100000) = 2r11000000 ifTrue: [ "two bytes"
+ nextIndex < limit ifFalse: [ ^self errorMalformedInput: aByteString ].
- (byte1 bitAnd: 16rE0) = 192 ifTrue: [ "two bytes"
- nextIndex < limit ifFalse: [ ^ self errorMalformedInput: aByteString ].
byte2 := aByteString byteAt: (nextIndex := nextIndex + 1).
+ (byte1 < 2r11000010) ifTrue: [ ^ self errorMalformedInput: aByteString ]. "other requirements are covered by initial bit mask"
+ (byte2 bitAnd: 16rC0) = 16r80 ifFalse: [^ self errorMalformedInput: aByteString].
+ unicode := ((byte1 bitAnd: 2r00011111) bitShift: 6) + (byte2 bitAnd: continuationByteMask)].
+
+ (byte1 bitAnd: 2r11110000) = 2r11100000 ifTrue: [ "three bytes"
- (byte2 bitAnd: 16rC0) = 16r80 ifFalse:[ ^self errorMalformedInput: aByteString ].
- unicode := ((byte1 bitAnd: 31) bitShift: 6) + (byte2 bitAnd: 63)].
- (byte1 bitAnd: 16rF0) = 224 ifTrue: [ "three bytes"
(nextIndex + 2) <= limit ifFalse: [ ^ self errorMalformedInput: aByteString ].
byte2 := aByteString byteAt: (nextIndex := nextIndex + 1).
(byte2 bitAnd: 16rC0) = 16r80 ifFalse:[ ^self errorMalformedInput: aByteString ].
+ ((byte1 bitAnd: 2r00001111) = 2r0 and: [byte2 < 2r10100000]) ifTrue: [ ^self errorMalformedInput: aByteString ].
+ ((byte1 = 2r11101101) and: [(byte2 bitAnd: 2r00100000) = 2r00100000]) ifTrue: [
+ "reserved codepoints"
+ ^self errorMalformedInput: aByteString ].
byte3 := aByteString byteAt: (nextIndex := nextIndex + 1).
(byte3 bitAnd: 16rC0) = 16r80 ifFalse:[ ^self errorMalformedInput: aByteString ].
+ unicode := ((byte1 bitAnd: 2r00001111) bitShift: 12) + ((byte2 bitAnd: continuationByteMask) bitShift: 6)
+ + (byte3 bitAnd: continuationByteMask)].
+
+ (byte1 bitAnd: 2r11111000) = 2r11110000 ifTrue: [ "four bytes"
- unicode := ((byte1 bitAnd: 15) bitShift: 12) + ((byte2 bitAnd: 63) bitShift: 6)
- + (byte3 bitAnd: 63)].
- (byte1 bitAnd: 16rF8) = 240 ifTrue: [ "four bytes"
(nextIndex + 3) <= limit ifFalse: [ ^ self errorMalformedInput: aByteString ].
byte2 := aByteString byteAt: (nextIndex := nextIndex + 1).
(byte2 bitAnd: 16rC0) = 16r80 ifFalse:[ ^self errorMalformedInput: aByteString ].
+ ((byte1 = 2r11110000) and: [byte2 < 2r10010000]) ifTrue: [ ^self errorMalformedInput: aByteString ].
byte3 := aByteString byteAt: (nextIndex := nextIndex + 1).
(byte3 bitAnd: 16rC0) = 16r80 ifFalse:[ ^self errorMalformedInput: aByteString ].
byte4 := aByteString byteAt: (nextIndex := nextIndex + 1).
(byte4 bitAnd: 16rC0) = 16r80 ifFalse:[ ^self errorMalformedInput: aByteString ].
+ unicode := ((byte1 bitAnd: 2r00000111) bitShift: 18) +
+ ((byte2 bitAnd: continuationByteMask) bitShift: 12) +
+ ((byte3 bitAnd: continuationByteMask) bitShift: 6) +
+ (byte4 bitAnd: continuationByteMask)].
+
- unicode := ((byte1 bitAnd: 16r7) bitShift: 18) +
- ((byte2 bitAnd: 63) bitShift: 12) +
- ((byte3 bitAnd: 63) bitShift: 6) +
- (byte4 bitAnd: 63)].
unicode ifNil: [ ^self errorMalformedInput: aByteString ].
unicode = 16rFEFF ifFalse: [ "Skip byte order mark"
outStream nextPut: (Unicode value: unicode) ].
lastIndex := nextIndex + 1.
(nextIndex := ByteString findFirstInString: aByteString inSet: latin1Map startingAt: lastIndex) = 0 ] whileFalse.
^outStream
next: aByteString size - lastIndex + 1 putAll: aByteString startingAt: lastIndex;
contents
!
More information about the Squeak-dev
mailing list
|