io: support piped streams in slurp

This commit is contained in:
Danny Robson 2016-04-19 14:52:05 +10:00
parent 568af11a0a
commit aa780963e0
2 changed files with 32 additions and 6 deletions

30
io.cpp
View File

@ -82,16 +82,34 @@ util::slurp (FILE *stream)
if (fstat (desc, &meta) < 0)
errno_error::throw_code ();
// allocate a buffer we think is the correct size
std::vector<char> buf;
buf.resize (meta.st_size);
// read as much as possible, then resize to the actual length
auto res = fread (buf.data (), 1, meta.st_size, stream);
if (!ferror (stream))
// we think we know the size, so try to do a simple read
if (meta.st_size) {
buf.resize (meta.st_size);
// read as much as possible, then resize to the actual length
auto res = fread (buf.data (), 1, meta.st_size, stream);
buf.resize (res);
}
// try reading small chunks until we've hit the end. important for
// handling pipe streams (like from popen) which report a zero size.
constexpr size_t CHUNK_SIZE = 128;
size_t cursor = buf.size ();
while (!feof (stream) && !ferror (stream)) {
auto oldsize = buf.size ();
buf.resize (oldsize + CHUNK_SIZE);
auto res = fread (buf.data () + cursor, 1, CHUNK_SIZE, stream);
if (res != CHUNK_SIZE)
buf.resize (oldsize + res);
}
if (ferror (stream))
throw stream_error ();
CHECK (feof (stream));
return buf;
}

8
io.hpp
View File

@ -142,6 +142,14 @@ namespace util {
private:
const boost::filesystem::path m_path;
};
class stream_error : public std::exception {
public:
virtual ~stream_error () { ; }
virtual const char* what (void) const noexcept
{ return "error on C stream"; }
};
}
#ifdef PLATFORM_WIN32