io: add an fd overload for slurp

This commit is contained in:
Danny Robson 2018-10-18 12:51:56 +11:00
parent 0de176591d
commit f21369c15a
2 changed files with 73 additions and 4 deletions

51
io.cpp
View File

@ -122,6 +122,57 @@ template std::vector<char> cruft::slurp (FILE*);
template std::vector<std::byte> cruft::slurp (FILE*);
///////////////////////////////////////////////////////////////////////////////
template <typename ValueT>
std::vector<ValueT>
cruft::slurp (posix::fd &src)
{
struct stat meta;
posix::error::try_value (fstat (src, &meta));
std::vector<ValueT> buf;
// 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 const res = cruft::posix::error::try_call (
::read, src.native (), buf.data (), meta.st_size
);
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 = 1024;
while (1) {
// Make room for some more data
auto const oldsize = buf.size ();
buf.resize (oldsize + CHUNK_SIZE);
// Append the data
auto const res = cruft::posix::error::try_call (
::read, src.native (), buf.data () + oldsize, CHUNK_SIZE
);
buf.resize (oldsize + res);
// Bail if we've hit EOF
if (res == 0)
break;
}
return buf;
}
//-----------------------------------------------------------------------------
template std::vector<char> cruft::slurp (posix::fd&);
template std::vector<std::byte> cruft::slurp (posix::fd&);
//////////////////////////////////////////////////////////////////////////////
int
indenter::overflow (int ch) {

26
io.hpp
View File

@ -26,14 +26,32 @@
#endif
namespace cruft {
//-------------------------------------------------------------------------
/// Reads an entire file into memory.
///////////////////////////////////////////////////////////////////////////
/// Reads an entire file into memory in one operation.
template <typename T = std::byte>
std::vector<T> slurp (const std::experimental::filesystem::path&);
std::vector<T>
slurp (const std::experimental::filesystem::path&);
///------------------------------------------------------------------------
/// Read the entire contents of a FILE object into memory.
///
/// * This may trigger an arbitrary number of read calls.
/// * This may block indefinitely depending on the contents of the fd.
template <typename T = std::byte>
std::vector<T> slurp (FILE *);
std::vector<T>
slurp (FILE *);
///------------------------------------------------------------------------
/// Read the entire contents of a file-descriptor into memory in one
/// operation.
///
/// * This may trigger an arbitrary number of read calls.
/// * This may block indefinitely depending on the contents of the fd.
template <typename T = std::byte>
std::vector<T>
slurp (cruft::posix::fd&);
///////////////////////////////////////////////////////////////////////////