24 #ifndef STATICLIB_IO_BUFFERED_SOURCE_HPP
25 #define STATICLIB_IO_BUFFERED_SOURCE_HPP
33 #include "staticlib/config.hpp"
45 template <
typename Source, std::
size_t buf_size = 4096>
54 bool exhausted =
false;
59 std::array<char, buf_size> buffer;
77 src(std::move(src)) { }
100 src(std::move(other.src)),
101 exhausted(other.exhausted),
102 buffer(std::move(other.buffer)),
105 other.exhausted =
true;
117 src = std::move(other.src);
118 exhausted = other.exhausted;
119 other.exhausted =
true;
120 buffer = std::move(other.buffer);
135 size_t ulen = span.
size();
138 std::memcpy(span.
data(), buffer.data() + pos, ulen);
144 size_t uhead = avail;
145 if (!sl::support::is_streamsize(uhead)) {
146 uhead =
static_cast<size_t> (std::numeric_limits<std::streamsize>::max());
149 std::memcpy(span.
data(), buffer.data() + pos, uhead);
153 std::streamsize head =
static_cast<std::streamsize
> (uhead);
155 if (ulen > buffer.size()) {
157 size_t result = read_into_buffer(span.
data(), uhead, ulen - uhead);
158 size_t out = result + uhead;
159 return out > 0 ? out : std::char_traits<char>::eof();
162 avail = read_into_buffer(buffer.data(), 0, buffer.size());
165 size_t to_read_req = ulen - uhead;
166 size_t to_read = to_read_req <= avail ? to_read_req : avail;
167 if (!sl::support::is_streamsize(to_read + uhead)) {
168 to_read =
static_cast<size_t> (std::numeric_limits<std::streamsize>::max()) - uhead;
170 std::memcpy(span.
data() + uhead, buffer.data(), to_read);
174 return static_cast<std::streamsize
>(to_read + uhead);
176 return head == 0 ? std::char_traits<char>::eof() : head;
188 std::string
read_line(
const std::string& ending =
"\n",
size_t max_length = (1<<16)) {
191 while(line.length() < max_length && 1 ==
read({std::addressof(ch), 1})) {
193 if (ending.length() > 0 && ch == ending.back() && line.length() >= ending.length()) {
195 size_t sdiff = line.length() - ending.length();
196 for (
int i = static_cast<int>(ending.length()) - 2; i >= 0; i--) {
197 if (ending[i] != line[sdiff + i]) {
203 for (
size_t i = 0; i < ending.length(); i++) {
206 if (line.length() > 0) {
235 size_t read_into_buffer(
char* buf,
size_t offset,
size_t length) {
238 while (result < length) {
239 size_t ulen = length - result;
240 if (!sl::support::is_streamsize(ulen)) {
241 ulen =
static_cast<size_t> (std::numeric_limits<std::streamsize>::max());
243 std::streamsize amt = src.read({buf + offset + result,
static_cast<std::streamsize
> (ulen)});
244 if (std::char_traits<char>::eof() != amt) {
245 if (!sl::support::is_sizet(amt))
throw io_exception(TRACEMSG(
246 "Invalid result returned by underlying 'read' operation: [" + sl::support::to_string(amt) +
"]"));
247 result +=
static_cast<size_t> (amt);
266 template <
typename Source,
267 class =
typename std::enable_if<!std::is_lvalue_reference<Source>::value>::type>
279 template <
typename Source>