|
#include "line_input.hh" |
|
|
|
#include "../exception.hh" |
|
#include "../file.hh" |
|
#include "../read_compressed.hh" |
|
#include "chain.hh" |
|
|
|
#include <algorithm> |
|
#include <vector> |
|
|
|
namespace util { namespace stream { |
|
|
|
void LineInput::Run(const ChainPosition &position) { |
|
ReadCompressed reader(fd_); |
|
|
|
std::vector<char> carry; |
|
|
|
for (Link block(position); ; ++block) { |
|
char *to = static_cast<char*>(block->Get()); |
|
char *begin = to; |
|
char *end = to + position.GetChain().BlockSize(); |
|
std::copy(carry.begin(), carry.end(), to); |
|
to += carry.size(); |
|
while (to != end) { |
|
std::size_t got = reader.Read(to, end - to); |
|
if (!got) { |
|
|
|
block->SetValidSize(to - begin); |
|
++block; |
|
block.Poison(); |
|
return; |
|
} |
|
to += got; |
|
} |
|
|
|
|
|
char *newline; |
|
for (newline = to - 1; ; --newline) { |
|
UTIL_THROW_IF(newline < begin, Exception, "Did not find a newline in " << position.GetChain().BlockSize() << " bytes of input of " << NameFromFD(fd_) << ". Is this a text file?"); |
|
if (*newline == '\n') break; |
|
} |
|
|
|
|
|
carry.clear(); |
|
carry.resize(to - (newline + 1)); |
|
std::copy(newline + 1, to, &*carry.begin()); |
|
|
|
block->SetValidSize(newline + 1 - begin); |
|
} |
|
} |
|
|
|
}} |
|
|