[s isAtEnd] whileFalse: [result nextPut: s next]] writingAs: s collectionType
].
+s@(ReadStream traits) nextLine
+"Fixme: this should be more sophisticated for cross platform support"
+[ | result elem |
+ result: s collectionType new writer.
+ [s isAtEnd \/ [(elem: s next). elem = $\n]]
+ whileFalse: [result nextPut: elem].
+ s isAtEnd ifFalse: [result nextPut: elem].
+ result contents
+].
+
s@(ReadStream traits) do: block
"Call the block on all the elements in turn until the Stream is empty."
[
"Retract one element."
[s retract: 1].
+s@(PositionableStream traits) restoringPositionDo: block
+[ | pos |
+ pos: s position.
+ block ensure: [s position: pos].
+].
+
+
streams define: #PositionableReadStream
&parents: {PositionableStream. ReadStream}.
streams define: #PositionableWriteStream
m new `>> [regex: r. ]
].
+s@(String traits) regex
+[
+ Regex Regex newOn: s
+].
+
+r@(Regex Regex traits) matcher
+[
+ Regex Matcher newOn: r
+].
+
+
m@(Regex Matcher traits) subexpression: x
[ |se|
se: (m subexpressions at: x ifAbsent: [^ Nil]).
string =~ (Regex Matcher newOn: regex)
].
+string@(String traits) =~ regex@(Regex Regex traits)
+[
+ string =~ (Regex Matcher newOn: regex)
+].
+
m@(Regex Matcher traits) match: s@(String traits) from: fromStart
[ |res|
[
m matchee size <= pos ifTrue: [pos] ifFalse: [-1]
].
+
+s@(PositionableStream traits) upToRegex: pattern@(String traits)
+[
+ s upTo: pattern regex matcher
+].
+
+"fixme put this somewhere reasonable"
+
+s@(PositionableStream traits) upToRegex: str@(String traits)
+[
+ s upToRegex: str regex matcher
+].
+
+s@(PositionableStream traits) throughRegex: str@(String traits)
+[
+ s throughRegex: str regex matcher
+].
+
+s@(PositionableStream traits) scanForRegex: matcher@(Regex Matcher traits) &goThrough: goThrough
+[ | start data line |
+ goThrough `defaultsTo: False.
+ start: s position.
+ data: s collectionType new writer.
+ s restoringPositionDo:
+ [[s isAtEnd not. line: (s nextLine). line isNotNil] whileTrue:
+ [0 to: line size do: [| :pos found | found: (matcher match: line from: pos).
+ found >= 0 ifTrue: [(line first: (goThrough ifTrue: [found] ifFalse: [pos])) >> data.
+ ^ data contents]].
+ line >> data.
+ ].
+ ].
+ data contents
+].
+
+
+s@(PositionableStream traits) upToRegex: matcher@(Regex Matcher traits)
+[
+ s scanForRegex: matcher &goThrough: False
+].
+
+s@(PositionableStream traits) throughRegex: matcher@(Regex Matcher traits)
+[
+ s scanForRegex: matcher &goThrough: True
+].
+
+
+