summaryrefslogtreecommitdiffstats
path: root/src/build_log.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/build_log.cc')
-rw-r--r--src/build_log.cc38
1 files changed, 33 insertions, 5 deletions
diff --git a/src/build_log.cc b/src/build_log.cc
index 01fb001..5803ada 100644
--- a/src/build_log.cc
+++ b/src/build_log.cc
@@ -113,24 +113,52 @@ void BuildLog::Close() {
class LineReader {
public:
- explicit LineReader(FILE* file) : file_(file) {}
+ explicit LineReader(FILE* file)
+ : file_(file), buf_end_(buf_), line_start_(buf_), line_end_(NULL) {}
// Reads a \n-terminated line from the file passed to the constructor.
// On return, *line_start points to the beginning of the next line, and
// *line_end points to the \n at the end of the line. If no newline is seen
// in a fixed buffer size, *line_end is set to NULL. Returns false on EOF.
bool ReadLine(char** line_start, char** line_end) {
- if (!fgets(buf_, sizeof(buf_), file_))
- return false;
+ if (line_start_ >= buf_end_ || !line_end_) {
+ // Buffer empty, refill.
+ size_t size_read = fread(buf_, 1, sizeof(buf_), file_);
+ if (!size_read)
+ return false;
+ line_start_ = buf_;
+ buf_end_ = buf_ + size_read;
+ } else {
+ // Advance to next line in buffer.
+ line_start_ = line_end_ + 1;
+ }
- *line_start = buf_;
- *line_end = strchr(buf_, '\n');
+ line_end_ = (char*)memchr(line_start_, '\n', buf_end_ - line_start_);
+ if (!line_end_) {
+ // No newline. Move rest of data to start of buffer, fill rest.
+ size_t already_consumed = line_start_ - buf_;
+ size_t size_rest = (buf_end_ - buf_) - already_consumed;
+ memmove(buf_, line_start_, size_rest);
+
+ size_t read = fread(buf_ + size_rest, 1, sizeof(buf_) - size_rest, file_);
+ buf_end_ = buf_ + size_rest + read;
+ line_start_ = buf_;
+ line_end_ = (char*)memchr(line_start_, '\n', buf_end_ - line_start_);
+ }
+
+ *line_start = line_start_;
+ *line_end = line_end_;
return true;
}
private:
FILE* file_;
char buf_[256 << 10];
+ char* buf_end_; // Points one past the last valid byte in |buf_|.
+
+ char* line_start_;
+ // Points at the next \n in buf_ after line_start, or NULL.
+ char* line_end_;
};
bool BuildLog::Load(const string& path, string* err) {