--- /dev/null
- [ "a" ] [ 1 SBUF" cba" stream-read ] unit-test
- [ "ab" ] [ 2 SBUF" cba" stream-read ] unit-test
- [ "abc" ] [ 3 SBUF" cba" stream-read ] unit-test
- [ "abc" ] [ 4 SBUF" cba" stream-read ] unit-test
+USING: io.streams.string io kernel arrays namespaces make
+tools.test ;
+IN: io.streams.string.tests
+
+[ "line 1" CHAR: l ]
+[
+ "line 1\nline 2\nline 3" <string-reader>
+ dup stream-readln swap stream-read1
+]
+unit-test
+
+[ f ]
+[ "" <string-reader> stream-readln ]
+unit-test
+
+[ "xyzzy" ] [ [ "xyzzy" write ] with-string-writer ] unit-test
+
- 3 SBUF" cba" [ stream-read ] keep stream-read1
++[ "a" ] [ 1 "abc" <string-reader> stream-read ] unit-test
++[ "ab" ] [ 2 "abc" <string-reader> stream-read ] unit-test
++[ "abc" ] [ 3 "abc" <string-reader> stream-read ] unit-test
++[ "abc" ] [ 4 "abc" <string-reader> stream-read ] unit-test
+[ "abc" f ] [
++ 3 "abc" <string-reader> [ stream-read ] keep stream-read1
+] unit-test
+
+[
+ {
+ { "It seems " CHAR: J }
+ { "obs has lost h" CHAR: i }
+ { "s grasp on reality again.\n" f }
+ }
+] [
+ [
+ "It seems Jobs has lost his grasp on reality again.\n"
+ <string-reader> [
+ "J" read-until 2array ,
+ "i" read-until 2array ,
+ "X" read-until 2array ,
+ ] with-input-stream
+ ] { } make
+] unit-test
+
+[ "hello" "hi" ] [
+ "hello\nhi" <string-reader>
+ dup stream-readln
+ 2 rot stream-read
+] unit-test
+
+[ "hello" "hi" ] [
+ "hello\r\nhi" <string-reader>
+ dup stream-readln
+ 2 rot stream-read
+] unit-test
+
+[ "hello" "hi" ] [
+ "hello\rhi" <string-reader>
+ dup stream-readln
+ 2 rot stream-read
+] unit-test
--- /dev/null
- ! Copyright (C) 2003, 2009 Slava Pestov.
++! Copyright (C) 2003, 2009 Slava Pestov, Daniel Ehrenberg.
+! See http://factorcode.org/license.txt for BSD license.
+USING: accessors io kernel math namespaces sequences sbufs
- strings generic splitting continuations destructors
- io.streams.plain io.encodings math.order growable ;
++strings generic splitting continuations destructors sequences.private
++io.streams.plain io.encodings math.order growable io.streams.sequence ;
+IN: io.streams.string
+
+<PRIVATE
+
- : harden-as ( seq growble-exemplar -- newseq )
- underlying>> like ;
-
- : growable-read-until ( growable n -- str )
- >fixnum dupd tail-slice swap harden-as dup reverse-here ;
-
+SINGLETON: null-encoding
+
+M: null-encoding decode-char drop stream-read1 ;
+
+PRIVATE>
+
+M: growable dispose drop ;
+
+M: growable stream-write1 push ;
+M: growable stream-write push-all ;
+M: growable stream-flush drop ;
+
+: <string-writer> ( -- stream )
+ 512 <sbuf> ;
+
+: with-string-writer ( quot -- str )
+ <string-writer> swap [ output-stream get ] compose with-output-stream*
+ >string ; inline
+
- M: growable stream-read1 [ f ] [ pop ] if-empty ;
-
- : find-last-sep ( seq seps -- n )
- swap [ memq? ] curry find-last drop ;
-
- M: growable stream-read-until
- [ find-last-sep ] keep over [
- [ swap 1+ growable-read-until ] 2keep [ nth ] 2keep
- set-length
- ] [
- [ swap drop 0 growable-read-until f like f ] keep
- delete-all
- ] if ;
++! New implementation
+
- M: growable stream-read
- [
- drop f
- ] [
- [ length swap - 0 max ] keep
- [ swap growable-read-until ] 2keep
- set-length
- ] if-empty ;
++TUPLE: string-reader { underlying string read-only } { i array-capacity } ;
+
- M: growable stream-read-partial
- stream-read ;
++M: string-reader stream-read-partial stream-read ;
++M: string-reader stream-read sequence-read ;
++M: string-reader stream-read1 sequence-read1 ;
++M: string-reader stream-read-until sequence-read-until ;
++M: string-reader dispose drop ;
+
+: <string-reader> ( str -- stream )
- >sbuf dup reverse-here null-encoding <decoder> ;
++ 0 string-reader boa null-encoding <decoder> ;
+
+: with-string-reader ( str quot -- )
+ [ <string-reader> ] dip with-input-stream ; inline
+
+INSTANCE: growable plain-writer