EncodedStream.st
author Stefan Vogel <sv@exept.de>
Wed, 21 Aug 2013 16:07:18 +0200
changeset 15664 1b91431394a5
parent 15618 4d4bafe3d804
child 15963 2549ef06a310
child 18086 33a050555eb1
permissions -rw-r--r--
class: EncodedStream comment/format in: #documentation changed: #decodedStreamFor: #nextChunk Fix encode checking for FilteringStreams

"
 COPYRIGHT (c) 2004 by eXept Software AG
              All Rights Reserved

 This software is furnished under a license and may be used
 only in accordance with the terms of that license and with the
 inclusion of the above copyright notice.   This software may not
 be provided or otherwise made available to, or used by, any
 other person.  No title to or ownership of the software is
 hereby transferred.
"
"{ Package: 'stx:libbasic' }"

PeekableStream subclass:#EncodedStream
	instanceVariableNames:'encoder stream'
	classVariableNames:''
	poolDictionaries:''
	category:'Streams-Misc'
!

!EncodedStream class methodsFor:'documentation'!

copyright
"
 COPYRIGHT (c) 2004 by eXept Software AG
              All Rights Reserved

 This software is furnished under a license and may be used
 only in accordance with the terms of that license and with the
 inclusion of the above copyright notice.   This software may not
 be provided or otherwise made available to, or used by, any
 other person.  No title to or ownership of the software is
 hereby transferred.
"
!

documentation
"
    a stream which transparently decodes from an external decoding,
    looking for '{ Encoding: xxx' near the beginning of the file.

    especially targeted towards reading ST/X source files.
"
! !

!EncodedStream class methodsFor:'instance creation'!

stream:streamArg encoder:encoder
    ^ (self basicNew) stream:streamArg; encoder:encoder
! !

!EncodedStream class methodsFor:'utilities'!

decodedStreamFor:aStream
    "given a positionable stream, guess its encoding (by reading the
     first few lines, looking for a string with an encoding hint,
     and return an appropriate encoded string, which does the decoding
     on the fly. Used mostly to read UTF8 files (source code)"

    |encodingSymbol decoder decodedStream|

    aStream inputStream isPositionable ifTrue:[
        encodingSymbol := CharacterEncoder guessEncodingOfStream:aStream inputStream.
        decoder := self encoderFor:encodingSymbol.
        decoder isNil ifTrue:[
            "/ ascii or iso8895-1
            ^ aStream
        ].
        decodedStream := self stream:aStream encoder:decoder.
        decodedStream skipEncodingChunk.
    ] ifFalse:[
        "/ setup for no-encoding; 
        "/ switch to a real encoder later,
        "/ whenever an encoding pragma is encountered later by #nextChunk.
        decodedStream := self stream:aStream encoder:CharacterEncoder nullEncoderInstance.
    ].
    ^ decodedStream
!

encoderFor:anEncodingSymbol
    (anEncodingSymbol isNil
    or:[ anEncodingSymbol = #'iso8859-1' 
    or:[ anEncodingSymbol = #'ascii' ]]) ifTrue:[
        ^ nil
    ].
    ^ CharacterEncoder encoderFor:anEncodingSymbol.
! !

!EncodedStream methodsFor:'accessing'!

contentsSpecies

    "Not sure if this is ok"

    ^ stream contentsSpecies.

"/    ^UnicodeString

    "Created: / 14-06-2005 / 17:11:01 / janfrog"
!

encoder
    ^ encoder
!

encoder:something
    encoder := something.
!

inputStream
    ^ stream inputStream
!

lineNumber
    ^ stream lineNumber
!

pathName
    "if our base stream hat a pathname, delegate..."

    stream isNil ifTrue:[
        ^ nil.
    ].
    ^ stream pathName.
!

readStream
    ^ self
!

stream
    ^ stream
!

stream:something
    stream := something.
! !

!EncodedStream methodsFor:'stream protocol'!

atEnd
    ^ stream atEnd
!

close
    stream close
!

contents

    ^String streamContents:
        [:s|
        [ stream atEnd ] whileFalse:
            [s nextPut: stream next]
        ]

    "Created: / 25-02-2010 / 23:34:28 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!

cr
    self nextPutAll:(Character cr asString)
!

emphasis:anObject

    stream emphasis:anObject

    "Created: / 15-06-2005 / 11:16:33 / janfrog"
!

flush
    stream flush
!

isOpen
    ^ stream notNil and:[stream isOpen]
!

next

    ^encoder readNextCharacterFrom:stream

    "Created: / 14-06-2005 / 17:01:39 / janfrog"
!

next:charactersToRead

    ^encoder readNext:charactersToRead charactersFrom:stream

    "Created: / 16-06-2005 / 11:43:43 / masca"
!

nextChunk
    "as a side effect, check for an encoding chunk"
    
    |prevEncoder chunk|

    chunk := stream nextChunk.
    chunk isNil ifTrue:[
        ^ nil
    ].
    prevEncoder := encoder.
    (prevEncoder isNullEncoder and:[stream isPositionable not]) ifTrue:[
        "/ not already checked
        "/ check if we need lazy setup of the encoder
        "/ (used with non-positionable streams)
        (chunk includesString:'{ Encoding:') ifTrue:[
            |enc|

            enc := self class encoderFor:(CharacterEncoder guessEncodingOfBuffer:chunk).
            enc notNil ifTrue:[
                prevEncoder := encoder := enc.
            ].
        ]
    ].
    ^ prevEncoder decodeString:chunk
!

nextChunkPut:chunk
    stream nextChunkPut:(encoder encodeString:chunk)
!

nextPut:aCharacter
    self nextPutAll:(aCharacter asString).
!

nextPutAll:aCollection
    stream nextPutAll:(encoder encodeString:aCollection).
!

peek

    ^stream peek

    "Created: / 20-06-2005 / 10:13:03 / masca"
    "Modified: / 20-06-2005 / 13:06:14 / masca"
!

peekFor:aCharacter
    ^ stream peekFor:aCharacter
!

position
    ^ stream position
!

position0Based
    <resource: #obsolete>
    "to be obsoleted - use position"

    ^ stream position
!

position0Based:newPosition
    <resource: #obsolete>
    "to be obsoleted - use position"

    stream position:newPosition
!

position1Based
    <resource: #obsolete>
    "to be obsoleted - use position"

    ^ stream position + 1
!

position1Based:newPosition
    <resource: #obsolete>
    "to be obsoleted - use position"

    stream position:newPosition-1
!

position:newPosition
    stream position:newPosition
!

reset
    stream reset

    "Created: / 25-02-2010 / 23:37:14 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!

setToEnd
    stream setToEnd
!

size
    "not correct, but probably better than 0"

    "/ is that better?
    "/ self error:'size of input is unknown (due to decoding)'
    ^ stream size

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

syncData
    stream syncData
! !

!EncodedStream methodsFor:'testing'!

isEncodedStream
    ^ true
!

isReadable
    ^ stream isReadable
!

isWritable
    ^ stream isWritable
! !

!EncodedStream methodsFor:'utilities'!

skipEncodingChunk
    |pos chunk token|

    stream isPositionable ifFalse:[
        ^ self
    ].

    pos := self position.
    chunk := self nextChunk.
    [
        "/ if this is a valid chunk (i.e. not a comment or encoding-directive),
        "/ then position back, so it will be processed as usual.
"/ We could parse here, but this is overkill, since we are only interested in the fact,
"/ that there is anything else than a comment in the chunk.
"/        result := (Parser for:chunk)
"/            ignoreErrors:true;
"/            ignoreWarnings:true;
"/            parseMethodBody.

        token := (Scanner for:chunk)
                     ignoreErrors:true;
                     ignoreWarnings:true;
                     nextToken.

        token ~= #EOF ifTrue:[
            self position:pos
        ].
    ] on:Parser parseWarningSignal do:[:ex|
        "really ignore any error.
         Even setting ignorError will output diagnostics here
         during standalone startup when debugging"
        ex proceedWith:#ignore.
    ].

    "Modified: / 29-07-2011 / 17:42:11 / cg"
! !

!EncodedStream class methodsFor:'documentation'!

version
    ^ '$Header: /cvs/stx/stx/libbasic/EncodedStream.st,v 1.34 2013-08-21 14:07:18 stefan Exp $'
!

version_CVS
    ^ '$Header: /cvs/stx/stx/libbasic/EncodedStream.st,v 1.34 2013-08-21 14:07:18 stefan Exp $'
!

version_SVN
    ^ '$ Id: EncodedStream.st 10643 2011-06-08 21:53:07Z vranyj1  $'
! !