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

Consider the following code example:

#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 lib ++ vs gnu libstd ++:

$ 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 considers 0xff to be the end of the stream and it stops reading. Thus, this leads to two questions.

1) Is this a bug in libC ++ that I should report? My Google searches were not found.

2) Is there a good way around this problem?

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;
}

I suppose this is a binary conversion problem, but that does not explain why libstdc ++ is working correctly.

EDIT2

Using a file without binaries works fine:

ifstream ifs ("testin");

, - . , cin, .

+5
3

, lib++ ( , ecatmur). :

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();
         }
     }

. . , .

176822 svn libcxx. dylib, .

+5

, , . (@Howard Hinnant) :

@@ -104,7 +104,7 @@
     int __nread = _VSTD::max(1, __encoding_);
     for (int __i = 0; __i < __nread; ++__i)
     {
-        char __c = getc(__file_);
+        int __c = getc(__file_);
         if (__c == EOF)
             return traits_type::eof();
         __extbuf[__i] = static_cast<char>(__c);
@@ -131,7 +131,7 @@
                 if (__nread == sizeof(__extbuf))
                     return traits_type::eof();
                 {
-                    char __c = getc(__file_);
+                    int __c = getc(__file_);
                     if (__c == EOF)
                         return traits_type::eof();
                     __extbuf[__nread] = static_cast<char>(__c);

, getc char, , char 0xff int EOF (.. -1).

cin, __stdinbuf, lib++, cin; ifstream . basic_filebuf<char>.

libcxx/include/__std_stream , , ; , , .

+2

. binary, .

char. char , , . uint8_t .

- :

#include <cstdint>
using std::uint8_t;
istreambuf_iterator<uint8_t> eos;
+1
source

All Articles