Commit 1f998c76 authored by Kenton Varda's avatar Kenton Varda

Add readAllText()/readAllBytes() to syncronous InputStream.

Similar methods already exist on AsyncInputStream.
parent cdc5c91c
......@@ -112,5 +112,41 @@ KJ_TEST("VectorOutputStream") {
KJ_ASSERT(output.getWriteBuffer().begin() == output.getArray().begin() + 40);
}
class MockInputStream: public InputStream {
public:
MockInputStream(kj::ArrayPtr<const byte> bytes, size_t blockSize)
: bytes(bytes), blockSize(blockSize) {}
size_t tryRead(void* buffer, size_t minBytes, size_t maxBytes) override {
// Clamp max read to blockSize.
size_t n = kj::min(blockSize, maxBytes);
// Unless that's less than minBytes -- in which case, use minBytes.
n = kj::max(n, minBytes);
// But also don't read more data than we have.
n = kj::min(n, bytes.size());
memcpy(buffer, bytes.begin(), n);
bytes = bytes.slice(n, bytes.size());
return n;
}
private:
kj::ArrayPtr<const byte> bytes;
size_t blockSize;
};
KJ_TEST("InputStream::readAllText()") {
auto bigText = strArray(kj::repeat("foo bar baz"_kj, 12345), ",");
size_t blockSizes[] = { 1, 4, 256, bigText.size() };
for (size_t blockSize: blockSizes) {
KJ_CONTEXT(blockSize);
MockInputStream input(bigText.asBytes(), blockSize);
KJ_EXPECT(input.readAllText() == bigText);
}
}
} // namespace
} // namespace kj
......@@ -28,6 +28,7 @@
#include "miniposix.h"
#include <algorithm>
#include <errno.h>
#include "vector.h"
#if _WIN32
#ifndef NOMINMAX
......@@ -66,6 +67,43 @@ void InputStream::skip(size_t bytes) {
}
}
namespace {
Array<byte> readAll(InputStream& input, bool nulTerminate) {
Vector<Array<byte>> parts;
constexpr size_t BLOCK_SIZE = 4096;
for (;;) {
auto part = heapArray<byte>(BLOCK_SIZE);
size_t n = input.tryRead(part.begin(), part.size(), part.size());
if (n < part.size()) {
auto result = heapArray<byte>(parts.size() * BLOCK_SIZE + n + nulTerminate);
byte* pos = result.begin();
for (auto& p: parts) {
memcpy(pos, p.begin(), BLOCK_SIZE);
pos += BLOCK_SIZE;
}
memcpy(pos, part.begin(), n);
pos += n;
if (nulTerminate) *pos++ = '\0';
KJ_ASSERT(pos == result.end());
return result;
} else {
parts.add(kj::mv(part));
}
}
}
} // namespace
String InputStream::readAllText() {
return String(readAll(*this, true).releaseAsChars());
}
Array<byte> InputStream::readAllBytes() {
return readAll(*this, false);
}
void OutputStream::write(ArrayPtr<const ArrayPtr<const byte>> pieces) {
for (auto piece: pieces) {
write(piece.begin(), piece.size());
......
......@@ -65,6 +65,10 @@ public:
virtual void skip(size_t bytes);
// Skips past the given number of bytes, discarding them. The default implementation read()s
// into a scratch buffer.
String readAllText();
Array<byte> readAllBytes();
// Read until EOF and return as one big byte array or string.
};
class OutputStream {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment