Added utilty functions to read an entire file.
This commit is contained in:
@@ -7,8 +7,10 @@
|
||||
#include <cassert>
|
||||
#include <cstdint>
|
||||
#include <optional>
|
||||
#include <ranges>
|
||||
#include <span>
|
||||
#include <string>
|
||||
#include "../container/typeless_buffer.hpp"
|
||||
|
||||
namespace mijin
|
||||
{
|
||||
@@ -76,12 +78,26 @@ public:
|
||||
return readRaw(std::span(ptr, ptr + bytes), partial, outBytesRead);
|
||||
}
|
||||
|
||||
template<std::ranges::contiguous_range TRange>
|
||||
inline StreamError readRaw(TRange& range, bool partial = false, std::size_t* outBytesRead = nullptr)
|
||||
{
|
||||
const std::size_t bytes = std::distance(range.begin(), range.end()) * sizeof(std::ranges::range_value_t<TRange>);
|
||||
return readRaw(&*range.begin(), bytes, partial, outBytesRead);
|
||||
}
|
||||
|
||||
inline StreamError writeRaw(const void* data, std::size_t bytes)
|
||||
{
|
||||
const std::uint8_t* ptr = static_cast<const std::uint8_t*>(data);
|
||||
return writeRaw(std::span(ptr, ptr + bytes));
|
||||
}
|
||||
|
||||
template<std::ranges::contiguous_range TRange>
|
||||
inline StreamError writeRaw(const TRange& range)
|
||||
{
|
||||
const std::size_t bytes = std::distance(range.begin(), range.end()) * sizeof(std::ranges::range_value_t<TRange>);
|
||||
return writeRaw(&*range.begin(), bytes);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline StreamError read(T& value)
|
||||
{
|
||||
@@ -123,6 +139,12 @@ public:
|
||||
|
||||
StreamError readString(std::string& outString);
|
||||
StreamError writeString(std::string_view str);
|
||||
|
||||
StreamError getTotalLength(std::size_t& outLength);
|
||||
StreamError readRest(TypelessBuffer& outBuffer);
|
||||
|
||||
template<typename TChar = char>
|
||||
StreamError readAsString(std::basic_string<TChar>& outString);
|
||||
};
|
||||
|
||||
class FileStream : public Stream
|
||||
@@ -180,6 +202,42 @@ public:
|
||||
// public functions
|
||||
//
|
||||
|
||||
template<typename TChar>
|
||||
StreamError Stream::readAsString(std::basic_string<TChar>& outString)
|
||||
{
|
||||
static_assert(sizeof(TChar) == 1, "Can only read to 8-bit character types (char, unsigned char or char8_t");
|
||||
|
||||
// first try to allocate everything at once
|
||||
std::size_t length = 0;
|
||||
if (StreamError lengthError = getTotalLength(length); lengthError == StreamError::SUCCESS)
|
||||
{
|
||||
MIJIN_ASSERT(getFeatures().tell, "How did you find the length if you cannot tell()?");
|
||||
length -= tell();
|
||||
outString.resize(length);
|
||||
if (StreamError error = readRaw(outString.data(), length); error != StreamError::SUCCESS)
|
||||
{
|
||||
return error;
|
||||
}
|
||||
return StreamError::SUCCESS;
|
||||
}
|
||||
|
||||
// could not determine the size, read chunk-wise
|
||||
static constexpr std::size_t CHUNK_SIZE = 4096;
|
||||
std::array<TChar, CHUNK_SIZE> chunk;
|
||||
|
||||
outString.clear();
|
||||
while (!isAtEnd())
|
||||
{
|
||||
std::size_t bytesRead = 0;
|
||||
if (StreamError error = readRaw(chunk, true, &bytesRead); error != StreamError::SUCCESS)
|
||||
{
|
||||
return error;
|
||||
}
|
||||
outString.append(chunk.data(), chunk.data() + bytesRead);
|
||||
}
|
||||
return StreamError::SUCCESS;
|
||||
}
|
||||
|
||||
} // namespace mijin
|
||||
|
||||
#endif // !defined(MIJIN_IO_STREAM_HPP_INCLUDED)
|
||||
|
||||
Reference in New Issue
Block a user