PeekableStream.st
author claus
Thu, 02 Jun 1994 18:22:49 +0200
changeset 88 81dacba7a63a
parent 77 6c38ca59927f
child 93 e31220cb391f
permissions -rw-r--r--
*** empty log message ***

"
 COPYRIGHT (c) 1994 by Claus Gittinger
              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.
"

Stream subclass:#PeekableStream
       instanceVariableNames:''
       classVariableNames:''
       poolDictionaries:''
       category:'Streams'
!

PeekableStream comment:'
COPYRIGHT (c) 1994 by Claus Gittinger
              All Rights Reserved
'!

!PeekableStream class methodsFor:'documentation'!

copyright
"
 COPYRIGHT (c) 1994 by Claus Gittinger
              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.
"
!

version
"
$Header: /cvs/stx/stx/libbasic/PeekableStream.st,v 1.4 1994-06-02 16:21:13 claus Exp $
"
!

documentation
"
    abstract superclass for all Stream which support read-ahead
    (i.e. peeking) of one element.
    Concrete subclasses must implement a peek method.
"
! !

!PeekableStream methodsFor:'reading'!

peek 
    "return the next element of the stream without advancing (i.e.
     the following send of next will return this element again.)
     - we do not know here how to do it, it must be redefined in subclass"

    ^ self subclassResponsibility
!

peekFor:anObject 
    "if the next-to-be-read object is equal to the argument, anObject, read
     and return it. Otherwise, leave the receiver unaffected"

    self peek = anObject ifTrue:[
        self next.
        ^ anObject
    ].
    ^ false
!

nextPeek
    "advance to next element and return the peeked element"

    self next.
    ^ self peek
!

skipAny:skipCollection
    "skip all characters included in the argument-set.
     returns the next peeked element or nil, if the end-of-stream was reached."

    |nextOne|

    nextOne := self peek.
    [nextOne notNil and:[skipCollection includes:nextOne]] whileTrue:[
        self next.
        nextOne := self peek
    ].
    ^ nextOne

    "
     |s skipChars|

     s := ReadStream on:'some numbers1234with\in other99 stuff' withCRs.
     skipChars := 'abcdefghijklmnopqrstuvwxyz\ ' withCRs.
     s skipAny:skipChars.
     Transcript showCr:(Integer readFrom:s).
     s skipAny:skipChars.
     Transcript showCr:(Integer readFrom:s).
    "
!

skipSpaces
    "skip all spaces; returns the next peeked element or
     nil, if the end-of-stream was reached.
     The streams elements should be characters.
     Notice: this one skips only spaces (i.e. no cr, tabs etc)
             usually, skipSeparators is what you want."

    |nextOne|

    nextOne := self peek.
    [nextOne notNil and:[nextOne == Character space]] whileTrue:[
        self next.
        nextOne := self peek
    ].
    ^ nextOne

    "
     |s|

     s := ReadStream on:'one      two\three' withCRs.
     s skipSpaces.
     Transcript showCr:(s nextWord).
     s skipSpaces.
     Transcript showCr:(s nextWord).
     s skipSpaces.
     Transcript showCr:(s next displayString).
    "
!

skipSeparators
    "skip all whitespace; returns the next peeked element or
     nil, if the end-of-stream was reached.
     The streams elements should be characters.
     Notice: compare this method to skipSpaces"

    |nextOne|

    nextOne := self peek.
    [nextOne notNil and:[nextOne isSeparator]] whileTrue:[
        self next.
        nextOne := self peek
    ].
    ^ nextOne
    "
     |s|

     s := ReadStream on:'one      two\three' withCRs.
     s skipSeparators.
     Transcript showCr:(s nextWord).
     s skipSeparators.
     Transcript showCr:(s nextWord).
     s skipSeparators.
     Transcript showCr:(s next displayString).
    "
! 

skipSeparatorsExceptCR
    "skip all whitespace except carriage return; returns the 
     next peeked element or nil, if the end-of-stream was reached.
     The streams elements should be characters.
     Notice: compare this method to skipSpaces and skipSeparators"

    |nextOne|

    nextOne := self peek.
    [nextOne notNil 
     and:[nextOne isSeparator
     and:[nextOne ~~ Character cr]]] whileTrue:[
        self next.
        nextOne := self peek
    ].
    ^ nextOne
!

upTo:anObject
    "return a collection of the elements up-to
     (but excluding) the argument, element.
     The next read operation will return anObject.
     Return everything up to the end, if the stream-end is reached before."

    |answerStream element|

    answerStream := WriteStream on:(self contentsSpecies new).
    [self atEnd] whileFalse: [
        element := self peek.
        (element = anObject) ifTrue: [^answerStream contents].
        answerStream nextPut: element.
	self next
    ].
    ^ answerStream contents

    "(ReadStream on:'1234567890') upTo:$5"
    "(ReadStream on:'123456') upTo:$7"
    "(ReadStream on:#(1 2 3 4 5 6)) upTo:4"
    "(ReadStream on:'line 1
                     line 2') upTo:Character cr "
    "'Makefile' asFilename readStream upTo:Character cr"
!

upToSeparator
    "Return the next elements up to but not including the next separator.
     The elements are supposed to understand isSeparator."

    |answerStream element|

    answerStream := WriteStream on:(self contentsSpecies new).
    [self atEnd] whileFalse: [
        element := self peek.
        element isSeparator ifTrue: [^answerStream contents].
        answerStream nextPut: element.
        self next.
    ].
    ^ answerStream contents
! 

nextDecimalInteger
    "read the next integer in radix 10. dont skip whitespace.
     The streams elements should be characters."

    |nextOne value|

    nextOne := self peek.
    value := 0.
    [nextOne notNil and:[nextOne isDigitRadix:10]] whileTrue:[
        value := (value * 10) + nextOne digitValue.
        nextOne := self nextPeek
    ].
    ^ value
! !