How can i read a 0xFF in a file with libc++ istream_iterator?

c++, istream-iterator, libc++, libstdc++

Solution

Unfortunately there is still a bug in libc++ (in addition to the one ecatmur pointed out). Here is the fix:

Index: include/__std_stream
===================================================================
--- include/__std_stream    (revision 176092)
+++ include/__std_stream    (working copy)
@@ -150,7 +150,7 @@
     {
         for (int __i = __nread; __i > 0;)
         {
-            if (ungetc(__extbuf[--__i], __file_) == EOF)
+            if (ungetc(traits_type::to_int_type(__extbuf[--__i]), __file_) == EOF)
                 return traits_type::eof();
         }
     }

I will get this checked in asap. Sorry for the bug. Thanks for bringing it to my attention.

Fix Committed revision 176822 to the libcxx public svn trunk. The fix requires a re-compiled dylib even though the fix is in a header.

Problem

Consider the following example code: ``` #include <iostream> using namespace std; int main() { istreambuf_iterator<char> eos; istreambuf_iterator<char> iit(cin.rdbuf()); int i; for (i = 0; iit != eos; ++i, ++iit) { cout << *iit; } cout << endl << i << endl; } ``` And an input file containing the following: "foo\xffbar": ``` $ hexdump testin 0000000 66 6f 6f ff 62 61 72 0000007 ``` Now for the test using clang libc++ vs gnu libstdc++: ``` $ make test clang++ -std=c++11 -stdlib=libc++ -Wall -stdlib=libc++ -o bug-libcc bug.cpp clang++ -std=c++11 -stdlib=libc++ -Wall -stdlib=libstdc++ -o bug-libstd bug.cpp ./bug-libcc < testin foo 3 ./bug-libstd < testin foo�bar 7 ``` As you can see the libc++ version thinks the 0xff is the end of stream and it stops reading. So this leads to a couple of questions. 1) Is this a bug in libc++ that I should report? My google searches for existing bugs have turned up nothing. 2) Is there a good way to work around this issue? EDIT The following code works: ``` #include <iostream> #include <fstream> using namespace std; int main() { ifstream ifs ("testin", ios::binary); istreambuf_iterator<char> eos; istreambuf_iterator<char> iit(ifs.rdbuf()); int i; for (i = 0; iit != eos; ++i, ++iit) { cout << *iit; } cout << endl << i << endl; } ``` Leading me to believe that it is a binary conversion issue, but that doesn't explain why libstdc++ works properly. EDIT2 Using a file without binary works fine too: ``` ifstream ifs ("testin"); ``` So there is definitely something fishy going on. It looks like it might be an issue in the implementation of cin though, not the iterator.

Original source