#BUGFIX by stefan
Support real #peak of unicode characters
class: EncodedStream
class definition
removed:
#cr
#peekFor:
#skip:
#skipSeparators
comment/format in:
#contents
#isOpen
#position
changed:15 methods
--- a/EncodedStream.st Wed Jan 10 23:00:57 2018 +0100
+++ b/EncodedStream.st Wed Jan 10 23:01:58 2018 +0100
@@ -14,7 +14,7 @@
"{ NameSpace: Smalltalk }"
PeekableStream subclass:#EncodedStream
- instanceVariableNames:'encoder stream'
+ instanceVariableNames:'encoder stream peekChar'
classVariableNames:''
poolDictionaries:''
category:'Collections-Text-Encodings'
@@ -131,17 +131,6 @@
!EncodedStream methodsFor:'accessing'!
-contentsSpecies
-
- "Not sure if this is ok"
-
- ^ stream contentsSpecies.
-
-"/ ^UnicodeString
-
- "Created: / 14-06-2005 / 17:11:01 / janfrog"
-!
-
encoder
^ encoder
!
@@ -161,7 +150,15 @@
!
lineNumber
+ "the linenumber doesn't change when characters are decoded"
+
+ stream isNil ifTrue:[
+ ^ nil.
+ ].
^ stream lineNumber
+
+ "Modified: / 02-01-2018 / 20:12:18 / stefan"
+ "Modified (comment): / 09-01-2018 / 17:47:20 / stefan"
!
pathName
@@ -194,34 +191,40 @@
nextChunk
"as a side effect, check for an encoding chunk"
- |prevEncoder chunk|
+ |chunk|
- chunk := stream nextChunk.
- chunk isEmptyOrNil ifTrue:[
- ^ chunk.
- ].
+ chunk := super nextChunk.
- prevEncoder := encoder.
- (prevEncoder isNullEncoder and:[stream isPositionable not]) ifTrue:[
- "/ not already checked
+ (encoder isNullEncoder and:[stream isPositionable not]) ifTrue:[
+ "/ encoding not already checked
"/ check if we need lazy setup of the encoder
"/ (used with non-positionable streams)
- (chunk includesString:'{ Encoding:') ifTrue:[
+ "/ encoder for PositionableStream is set up in self class decodedStreamFor:
+ (chunk notNil and:[chunk includesString:'{ Encoding:']) ifTrue:[
|enc|
enc := self class encoderFor:(CharacterEncoder guessEncodingOfBuffer:chunk).
enc notNil ifTrue:[
- prevEncoder := encoder := enc.
+ encoder := enc.
+ ^ encoder decodeString:chunk.
].
- ]
+ ].
].
- ^ prevEncoder decodeString:chunk
- "Modified: / 16-02-2017 / 14:54:57 / stefan"
+ ^ chunk.
+
+ "Modified (format): / 04-01-2018 / 00:33:57 / stefan"
! !
!EncodedStream methodsFor:'queries'!
+contentsSpecies
+ ^ String
+
+ "Created: / 14-06-2005 / 17:11:01 / janfrog"
+ "Modified: / 10-01-2018 / 11:43:57 / stefan"
+!
+
isEncoderFor:encodingString
^ encoder isEncoderFor:encodingString
@@ -231,11 +234,16 @@
!EncodedStream methodsFor:'stream protocol'!
atEnd
- ^ stream atEnd
+ ^ peekChar isNil and:[stream atEnd]
+
+ "Modified: / 02-01-2018 / 21:47:17 / stefan"
!
close
+ peekChar := nil.
stream close
+
+ "Modified: / 09-01-2018 / 18:33:01 / stefan"
!
collection
@@ -248,9 +256,8 @@
!
contents
-
- ^String streamContents: [:s|
- [ self atEnd ] whileFalse:[
+ ^String streamContents:[:s|
+ [self atEnd] whileFalse:[
|ch|
ch := self next.
"/ decoder may decide to return nil from #next, even though the
@@ -262,10 +269,7 @@
]
"Created: / 25-02-2010 / 23:34:28 / Jan Vrany <jan.vrany@fit.cvut.cz>"
-!
-
-cr
- self nextPutAll:(Character cr asString)
+ "Modified (format): / 02-01-2018 / 19:35:10 / stefan"
!
emphasis:anObject
@@ -276,29 +280,52 @@
!
flush
+ peekChar := nil.
stream flush
+
+ "Modified: / 02-01-2018 / 19:17:40 / stefan"
!
isEmpty
- ^ stream isEmpty
-!
+ ^ stream isEmptyOrNil.
-isOpen
- ^ stream notNil and:[stream isOpen]
+ "Modified: / 02-01-2018 / 19:59:09 / stefan"
!
next
-
- ^encoder readNextCharacterFrom:stream
+ peekChar notNil ifTrue:[
+ |p|
+ p := peekChar.
+ peekChar := nil.
+ ^ p.
+ ].
+ ^ encoder readNextCharacterFrom:stream
"Created: / 14-06-2005 / 17:01:39 / janfrog"
+ "Modified: / 02-01-2018 / 19:19:29 / stefan"
!
-next:charactersToRead
+next:nCharactersToRead
+ |chars|
- ^encoder readNext:charactersToRead charactersFrom:stream
+ nCharactersToRead == 1 ifTrue:[
+ ^ self next.
+ ].
+ nCharactersToRead == 0 ifTrue:[
+ ^ ''.
+ ].
+
+ peekChar isNil ifTrue:[
+ ^ encoder readNext:nCharactersToRead charactersFrom:stream.
+ ].
+
+ chars := encoder readNext:nCharactersToRead-1 charactersFrom:stream.
+ chars := chars copyWithFirst:peekChar.
+ peekChar := nil.
+ ^ chars.
"Created: / 16-06-2005 / 11:43:43 / masca"
+ "Modified: / 03-01-2018 / 22:22:51 / stefan"
!
nextPut:aCharacter
@@ -316,19 +343,23 @@
!
peek
-
- ^stream peek
+ peekChar isNil ifTrue:[
+ peekChar := self next.
+ ].
+ ^ peekChar
"Created: / 20-06-2005 / 10:13:03 / masca"
"Modified: / 20-06-2005 / 13:06:14 / masca"
-!
-
-peekFor:aCharacter
- ^ stream peekFor:aCharacter
+ "Modified (format): / 02-01-2018 / 19:21:00 / stefan"
!
position
+ "only use #position/#position: to restore a previous position.
+ Computing relative positions does not work!!"
+
^ stream position
+
+ "Modified (comment): / 09-01-2018 / 17:49:55 / stefan"
!
position0Based
@@ -349,28 +380,44 @@
<resource: #obsolete>
"to be obsoleted - use position"
- ^ stream position + 1
+ ^ stream position1Based
+
+ "Modified: / 02-01-2018 / 20:00:57 / stefan"
!
position1Based:newPosition
<resource: #obsolete>
"to be obsoleted - use position"
- stream position:newPosition-1
+ stream position1Based:newPosition
+
+ "Modified: / 02-01-2018 / 20:00:46 / stefan"
!
position:newPosition
+ "only use #position/#position: to restore a previous position.
+ Computing relative positions does not work!!
+ Use #skip: to advance forward."
+
+ peekChar := nil.
stream position:newPosition
+
+ "Modified (comment): / 09-01-2018 / 17:53:04 / stefan"
!
reset
+ peekChar := nil.
stream reset
"Created: / 25-02-2010 / 23:37:14 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+ "Modified: / 02-01-2018 / 19:34:20 / stefan"
!
setToEnd
+ peekChar := nil.
stream setToEnd
+
+ "Modified (comment): / 09-01-2018 / 17:50:27 / stefan"
!
size
@@ -384,18 +431,6 @@
"Created: / 31-08-2012 / 16:52:40 / cg"
!
-skip: anInteger
-
- "/ Should skip on character basis, not on bytes. This works for XML reader
- ^stream skip: anInteger
-
- "Created: / 20-06-2005 / 13:06:06 / masca"
-!
-
-skipSeparators
- ^ stream skipSeparators
-!
-
sync
stream sync
!
@@ -412,6 +447,15 @@
"Created: / 04-02-2014 / 20:27:36 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
+isOpen
+ "for compatibility with externalStream:
+ return true, if this stream is open."
+
+ ^ stream notNil and:[stream isOpen].
+
+ "Modified (comment): / 09-01-2018 / 18:34:47 / stefan"
+!
+
isPositionable
^ stream isPositionable