Move 'peeking' methods to PeekableStream
authorStefan Vogel <sv@exept.de>
Mon, 08 May 2006 18:54:42 +0200
changeset 9356 dfc36db0f470
parent 9355 860d76b815aa
child 9357 529e704303d2
Move 'peeking' methods to PeekableStream
PeekableStream.st
--- a/PeekableStream.st	Mon May 08 15:21:53 2006 +0200
+++ b/PeekableStream.st	Mon May 08 18:54:42 2006 +0200
@@ -680,6 +680,53 @@
     ^ self peek
 !
 
+nextUpTo:anObject
+    "read a collection of all objects up-to anObject and return these
+     elements, but excluding anObject. 
+     The next read operation will return anObject.
+     If anObject is not encountered, all elements up to the end are read
+     and returned, and the stream is positioned at the end.
+     Compare this with #upTo: which positions behind anObject"
+
+    |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
+
+    "
+     |s|
+     s := ReadStream on:#(1 2 3 4 5 6 7 8).
+     Transcript showCR:(s nextUpTo:4).  
+     Transcript showCR:s next
+
+     |s|
+     s := ReadStream on:#(1 2 3 4 5 6 7 8).
+     Transcript showCR:(s upTo:4).  
+     Transcript showCR:s next
+
+     |s|
+     s := ReadStream on:#(1 2 3 4 5 6 7 8).
+     Transcript showCR:(s nextUpTo:9).  
+     Transcript showCR:s next
+
+     |s|
+     s := ReadStream on:#(1 2 3 4 5 6 7 8).
+     Transcript showCR:(s upTo:9).  
+     Transcript showCR:s next
+    "
+
+    "Created: 24.1.1997 / 14:08:35 / cg"
+    "Modified: 24.1.1997 / 14:09:49 / cg"
+!
+
 peek 
     "return the next element of the stream without advancing (i.e.
      the following send of next will return this element again.)
@@ -699,6 +746,18 @@
     ^ false
 !
 
+peekOrNil
+    "like #peek, this returns the next readAhead element, if available.
+     However, unlike #peek, this does not raise an atEnd-query signal - even
+     if handled. Instead, nil is returned immediately."
+
+    self atEnd ifTrue:[^ nil].
+    ^ self peek
+
+    "Created: / 5.3.1998 / 02:56:49 / cg"
+    "Modified: / 5.3.1998 / 13:45:07 / cg"
+!
+
 upToMatching:aBlock
     "Return the next elements up to but not including the next element
      for which aBlock returns true.
@@ -753,10 +812,144 @@
     "Modified: 4.1.1997 / 23:38:05 / cg"
 ! !
 
+!PeekableStream methodsFor:'reading-strings'!
+
+nextAlphaNumericWord
+    "read the next word (i.e. up to non letter-or-digit).
+     Return a string containing those characters.
+     Any leading non-alphaNumeric chars are skipped."
+
+    |s c|
+
+    [self atEnd
+     or:[(c := self peek) isLetterOrDigit]] whileFalse:[
+        self next 
+    ].
+
+    self atEnd ifTrue:[^ nil].
+
+    s := ''.
+
+    [self atEnd not
+     and:[(c := self peek) isLetterOrDigit]] whileTrue:[ 
+        s := s copyWith:c. 
+        self next 
+    ].
+
+    s size == 0 ifTrue:[^ nil].
+    ^ s.
+
+    "
+     |s|
+
+     s := 'hello world 1234 foo1 foo2' readStream.
+     [s atEnd] whileFalse:[
+        Transcript showCR:(s nextAlphaNumericWord).
+     ].
+    "
+
+    "
+     |s|
+
+     s := 'hello +++ #world ###123###abc### 1234 foo1 foo2' readStream.
+     [s atEnd] whileFalse:[
+        Transcript showCR:(s nextAlphaNumericWord).
+     ].
+    "
+
+    "Modified: 15.5.1996 / 17:51:42 / cg"
+!
+
+nextMatching:matchBlock1 thenMatching:matchBlock2
+    "read the next word. The first character must match matchBlock1,
+     remaining characters must match matchBlock2.
+     Return a string containing those characters."
+
+    |s c|
+
+    self atEnd ifTrue:[^ nil].
+    (matchBlock1 value:self peek) ifFalse:[^ nil].
+
+    s := self next asString.
+
+    [self atEnd not
+     and:[matchBlock2 value:(c := self peek)]] whileTrue:[ 
+        s := s copyWith:c. 
+        self next 
+    ].
+
+    s size == 0 ifTrue:[^ nil].
+    ^ s.
+
+    "
+     |s|
+
+     s := 'hello_world_1234 foo1 foo2' readStream.
+     s nextMatching:[:c | c isLetter] thenMatching:[:c | c isLetterOrDigit or:[c == $_]].
+    "
+!
+
+nextSymbol
+    "read the next selector-symbol (i.e. up to non letter-or-digit).
+     Return a string containing those characters.
+     Any leading non-alphaNumeric chars are skipped."
+
+    |symbol c symbolStream|
+
+    [self atEnd
+     or:[(c := self peek) isLetterOrDigit]] whileFalse:[
+        self next 
+    ].
+
+    self atEnd ifTrue:[^ nil].
+
+    symbolStream := '' writeStream.
+
+    [self atEnd not
+     and:[(c := self peek) isLetterOrDigit or:[c == $:]]] whileTrue:[
+        symbolStream nextPut:c.
+        self next 
+    ].
+
+    symbol := symbolStream contents.
+    symbol size == 0 ifTrue:[^ nil].
+    ^ symbol.
+
+    "
+     |s|
+
+     s := 'hello: world 1234 foo1 foo2:' readStream.
+     [s atEnd] whileFalse:[
+        Transcript showCR:(s nextSymbol).
+     ].
+    "
+
+    "
+     |s|
+
+     s := 'hello +++ #world ###123###abc### 1234 foo1 foo2' readStream.
+     [s atEnd] whileFalse:[
+        Transcript showCR:(s nextAlphaNumericWord).
+     ].
+    "
+
+    "Modified: 15.5.1996 / 17:51:42 / cg"
+!
+
+nextWord
+    "return the next characters which form an alphanumeric word
+     (i.e. everything upTo (but excluding) the next non alphanumeric
+      element)"
+
+    ^ self nextAlphaNumericWord
+
+    "Modified: 15.5.1996 / 17:39:32 / cg"
+! !
+
 !PeekableStream class methodsFor:'documentation'!
 
 version
-    ^ '$Header: /cvs/stx/stx/libbasic/PeekableStream.st,v 1.28 2005-04-25 14:31:26 stefan Exp $'
+    ^ '$Header: /cvs/stx/stx/libbasic/PeekableStream.st,v 1.29 2006-05-08 16:54:42 stefan Exp $'
 ! !
 
 PeekableStream initialize!