Index: libcfa/src/collections/string.cfa
===================================================================
--- libcfa/src/collections/string.cfa	(revision aae9c1797b4b9d902f4bd84cca9600885f694007)
+++ libcfa/src/collections/string.cfa	(revision efe39bb236858e14a848e0a628d8646a263e349c)
@@ -129,37 +129,10 @@
 
 void ?|?( ifstream & in, string & this ) {
-    (ifstream &)(in | this); ends( in );
+    in | (*this.inner);
 }
 
 ifstream & ?|?( ifstream & is, _Istream_Sstr f ) {
- 	// .---------------,
- 	// | | | | |...|0|0| null terminator and guard if missing
- 	// `---------------'
-	enum { gwd = 128 + 1, wd = gwd - 1 };				// guard and unguard width
-	char cstr[gwd];										// read in chunks
-	bool cont = false;
-
-	_Istream_Cstr cf = { cstr, (_Istream_str_base)f };
-	if ( ! cf.flags.rwd ) cf.wd = wd;
-
-	cstr[wd] = '\0';									// guard null terminate string
-	try {
-		is | cf;
-	} catch( cstring_length * ) {
-		cont = true;
-	} finally {
-        if ( ! cf.flags.ignore ) f.s = cstr;			// ok to initialize string
-	} // try
-	for ( ; cont; )  {									// overflow read ?
-		cont = false;
-		try {
-			is | cf;
-		} catch( cstring_length * ) {
-			cont = true;								// continue not allowed
-		} finally {
-			if ( ! cf.flags.ignore ) f.s += cstr;		// build string chunk at a time
-		} // try
-	} // for
-	return is;
+ 	_Istream_Rstr f2 = {f.s.inner, (_Istream_str_base)f};
+    return is | f2;
 } // ?|?
 
Index: libcfa/src/collections/string_res.cfa
===================================================================
--- libcfa/src/collections/string_res.cfa	(revision aae9c1797b4b9d902f4bd84cca9600885f694007)
+++ libcfa/src/collections/string_res.cfa	(revision efe39bb236858e14a848e0a628d8646a263e349c)
@@ -245,4 +245,44 @@
     s = temp;
     return in;
+}
+
+void ?|?( ifstream & in, string_res & this ) {
+    (ifstream &)(in | this); ends( in );
+}
+
+ifstream & ?|?( ifstream & is, _Istream_Rstr f ) {
+ 	// .---------------,
+ 	// | | | | |...|0|0| null terminator and guard if missing
+ 	// `---------------'
+	enum { gwd = 128 + 1, wd = gwd - 1 };				// guard and unguard width
+	char cstr[gwd];										// read in chunks
+	bool cont = false;
+
+	_Istream_Cstr cf = { cstr, (_Istream_str_base)f };
+	if ( ! cf.flags.rwd ) cf.wd = wd;
+
+	cstr[wd] = '\0';									// guard null terminate string
+	try {
+		is | cf;
+	} catch( cstring_length * ) {
+		cont = true;
+	} finally {
+        if ( ! cf.flags.ignore ) *(f.s) = cstr;			// ok to initialize string
+	} // try
+	for ( ; cont; )  {									// overflow read ?
+		cont = false;
+		try {
+			is | cf;
+		} catch( cstring_length * ) {
+			cont = true;								// continue not allowed
+		} finally {
+			if ( ! cf.flags.ignore ) *(f.s) += cstr;	// build string chunk at a time
+		} // try
+	} // for
+	return is;
+} // ?|?
+
+void ?|?( ifstream & in, _Istream_Rstr f ) {
+    (ifstream &)(in | f); ends( in );
 }
 
Index: libcfa/src/collections/string_res.hfa
===================================================================
--- libcfa/src/collections/string_res.hfa	(revision aae9c1797b4b9d902f4bd84cca9600885f694007)
+++ libcfa/src/collections/string_res.hfa	(revision efe39bb236858e14a848e0a628d8646a263e349c)
@@ -102,4 +102,29 @@
 void ?|?(ofstream &out, const string_res &s);
 ifstream & ?|?(ifstream &in, string_res &s);
+void ?|?( ifstream & in, string_res & this );
+
+struct _Istream_Rstr {
+	string_res * s;
+	inline _Istream_str_base;
+}; // _Istream_Rstr
+
+static inline {
+	// read width does not include null terminator
+	_Istream_Rstr wdi( unsigned int rwd, string_res & s ) { return (_Istream_Rstr)@{ &s, {{0p}, rwd, {.flags.rwd : true}} }; }
+	_Istream_Rstr getline( string_res & s, const char delimiter = '\n' ) {
+		return (_Istream_Rstr)@{ &s, {{.delimiter : { delimiter, '\0' } }, -1, {.flags.delimiter : true, .flags.inex : true}} };
+	}
+	_Istream_Rstr & getline( _Istream_Rstr & fmt, const char delimiter = '\n' ) {
+		fmt.delimiter[0] = delimiter; fmt.delimiter[1] = '\0'; fmt.flags.delimiter = true; fmt.flags.inex = true; return fmt;
+	}
+	_Istream_Rstr incl( const char scanset[], string_res & s ) { return (_Istream_Rstr)@{ &s, {{scanset}, -1, {.flags.inex : false}} }; }
+	_Istream_Rstr & incl( const char scanset[], _Istream_Rstr & fmt ) { fmt.scanset = scanset; fmt.flags.inex = false; return fmt; }
+	_Istream_Rstr excl( const char scanset[], string_res & s ) { return (_Istream_Rstr)@{ &s, {{scanset}, -1, {.flags.inex : true}} }; }
+	_Istream_Rstr & excl( const char scanset[], _Istream_Rstr & fmt ) { fmt.scanset = scanset; fmt.flags.inex = true; return fmt; }
+	_Istream_Rstr ignore( string_res & s ) { return (_Istream_Rstr)@{ &s, {{0p}, -1, {.flags.ignore : true}} }; }
+	_Istream_Rstr & ignore( _Istream_Rstr & fmt ) { fmt.flags.ignore = true; return fmt; }
+} // distribution
+ifstream & ?|?( ifstream & is, _Istream_Rstr f );
+void ?|?( ifstream & is, _Istream_Rstr t );
 
 // Concatenation
Index: tests/collections/.expect/string-istream-manip.txt
===================================================================
--- tests/collections/.expect/string-istream-manip.txt	(revision aae9c1797b4b9d902f4bd84cca9600885f694007)
+++ tests/collections/.expect/string-istream-manip.txt	(revision efe39bb236858e14a848e0a628d8646a263e349c)
@@ -12,2 +12,15 @@
 12 wwwwwwww
 13 wwwwwwww
+1 yyyyyyyyyyyyyyyyyyyy
+2 abcxxx
+3 abcxxx
+4 aaaaaaaa
+5 aaaaaaaa
+6 aabbccbb
+7 dddwww
+8 dddwww
+9 dddwww
+10 aaaaaaaa
+11 wwwwwwww
+12 wwwwwwww
+13 wwwwwwww
Index: tests/collections/.in/string-istream-manip.txt
===================================================================
--- tests/collections/.in/string-istream-manip.txt	(revision aae9c1797b4b9d902f4bd84cca9600885f694007)
+++ tests/collections/.in/string-istream-manip.txt	(revision efe39bb236858e14a848e0a628d8646a263e349c)
@@ -5,2 +5,8 @@
 abcyyy
 aaaaaaaaxxxxxxxxaabbccbbdddwwwbbbbbbbbwwwwwwwwaaaaaaaawwwwwwww
+abc 
+abc 
+xx
+abcxxx
+abcyyy
+aaaaaaaaxxxxxxxxaabbccbbdddwwwbbbbbbbbwwwwwwwwaaaaaaaawwwwwwww
Index: tests/collections/string-istream-manip.cfa
===================================================================
--- tests/collections/string-istream-manip.cfa	(revision aae9c1797b4b9d902f4bd84cca9600885f694007)
+++ tests/collections/string-istream-manip.cfa	(revision efe39bb236858e14a848e0a628d8646a263e349c)
@@ -2,4 +2,5 @@
 #include <fstream.hfa>
 #include <collections/string.hfa>
+#include <collections/string_res.hfa>
 
 int main() {
@@ -11,5 +12,23 @@
         sin | s;                                        sout | "2" | s;
         sin | ignore( s );                              sout | "3" | s;
-         sin | wdi( 8, s );                             sout | "4" | s;
+        sin | wdi( 8, s );                              sout | "4" | s;
+        sin | ignore( wdi( 8, s ) );                    sout | "5" | s;
+
+        sin | incl( "abc", s );                         sout | "6" | s;
+        sin | excl( "abc", s );                         sout | "7" | s;
+        sin | ignore( incl( "abc", s ) );               sout | "8" | s;
+        sin | ignore( excl( "abc", s ) );               sout | "9" | s;
+        sin | incl( "abc", wdi( 8, s ) );               sout | "10" | s;
+        sin | excl( "abc", wdi( 8, s ) );               sout | "11" | s;
+        sin | ignore( incl( "abc", wdi( 8, s ) ) );     sout | "12" | s;
+        sin | ignore( excl( "abc", wdi( 8, s ) ) );     sout | "13" | s;
+    }
+    {
+        string_res s = "yyyyyyyyyyyyyyyyyyyy";
+        char sk[] = "abc";
+        sin | "abc " | skip( sk ) | skip( 5 );          sout | "1" | s;
+        sin | s;                                        sout | "2" | s;
+        sin | ignore( s );                              sout | "3" | s;
+        sin | wdi( 8, s );                              sout | "4" | s;
         sin | ignore( wdi( 8, s ) );                    sout | "5" | s;
 
