Index: third_party/crazy_linker/crazy_linker/src/crazy_linker_line_reader.cpp |
diff --git a/third_party/crazy_linker/crazy_linker/src/crazy_linker_line_reader.cpp b/third_party/crazy_linker/crazy_linker/src/crazy_linker_line_reader.cpp |
new file mode 100644 |
index 0000000000000000000000000000000000000000..2f3ef727cf48b6de0cc236d6a0326bf99583d393 |
--- /dev/null |
+++ b/third_party/crazy_linker/crazy_linker/src/crazy_linker_line_reader.cpp |
@@ -0,0 +1,125 @@ |
+// Copyright (c) 2013 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#include "crazy_linker_line_reader.h" |
+ |
+#include "crazy_linker_debug.h" |
+ |
+// Set to 1 to enable debug logs here. |
+#define DEBUG_LINE_READER 0 |
+ |
+#define LLOG(...) LOG_IF(DEBUG_LINE_READER, __VA_ARGS__) |
+ |
+namespace crazy { |
+ |
+LineReader::LineReader() : fd_(), buff_(buff0_) { |
+ Reset(); |
+ eof_ = true; |
+} |
+ |
+LineReader::LineReader(const char* path) : fd_(), buff_(buff0_) { |
+ Open(path); |
+} |
+ |
+LineReader::~LineReader() { |
+ Reset(); |
+} |
+ |
+void LineReader::Open(const char* path) { |
+ Reset(); |
+ eof_ = !fd_.OpenReadOnly(path); |
+} |
+ |
+void LineReader::Reset() { |
+ if (buff_ != buff0_) |
+ ::free(buff_); |
+ |
+ eof_ = false; |
+ line_start_ = 0; |
+ line_len_ = 0; |
+ buff_size_ = 0; |
+ buff_capacity_ = sizeof buff0_; |
+ buff_ = buff0_; |
+} |
+ |
+bool LineReader::GetNextLine() { |
+ // Eat previous line. |
+ line_start_ += line_len_; |
+ line_len_ = 0; |
+ |
+ for (;;) { |
+ LLOG("%s: LOOP line_start=%d buff_size=%d buff_capacity=%d\n", |
+ __FUNCTION__, line_start_, buff_size_, buff_capacity_); |
+ |
+ // Find the end of the current line in the current buffer. |
+ const char* line = buff_ + line_start_; |
+ const char* line_end = reinterpret_cast<const char*>(::memchr(line, '\n', buff_size_ - line_start_)); |
bulach
2013/09/09 16:14:15
nit: >80cols here and 62 below
digit1
2013/09/10 09:23:30
Done.
|
+ if (line_end != NULL) { |
+ // Found one, return it directly. |
+ line_len_ = static_cast<size_t>(line_end + 1 - line); |
+ LLOG("%s: LINE line_start=%d line_len=%d '%.*s'\n", |
+ __FUNCTION__, line_start_, line_len_, line_len_, buff_ + line_start_); |
+ return true; |
+ } |
+ |
+ // Eat the start of the buffer |
+ if (line_start_ > 0) { |
+ ::memmove(buff_, buff_ + line_start_, buff_size_ - line_start_); |
+ buff_size_ -= line_start_; |
+ line_start_ = 0; |
+ LLOG("%s: MOVE buff_size=%d\n", __FUNCTION__, buff_size_); |
+ } |
+ |
+ // Handle end of input now. |
+ if (eof_) { |
+ // If there is a last line that isn't terminated by a newline, and |
+ // there is room for it in the buffer. Manually add a \n and return |
+ // the line. |
+ if (buff_size_ > 0 && buff_size_ < buff_capacity_) { |
+ buff_[buff_size_++] = '\n'; |
+ line_len_ = buff_size_; |
+ LLOG("%s: EOF_LINE buff_size=%d '%.*s'\n", |
+ __FUNCTION__, buff_size_, buff_size_, buff_); |
+ return true; |
+ } |
+ // Otherwise, ignore the last line. |
+ LLOG("%s: EOF\n", __FUNCTION__); |
+ return false; |
+ } |
+ |
+ // Before reading more data, grow the buffer if needed. |
+ if (buff_size_ == buff_capacity_) { |
+ size_t new_capacity = buff_capacity_ * 2; |
+ void* old_buff = (buff_ == buff0_) ? NULL : buff_; |
+ buff_ = static_cast<char*>(::realloc(old_buff, new_capacity)); |
+ if (old_buff != buff_) |
+ ::memcpy(buff_, buff0_, buff_capacity_); |
+ |
+ buff_capacity_ = new_capacity; |
+ LLOG("%s: GROW buff_size=%d buff_capacity=%d '%.*s'\n", |
+ __FUNCTION__, buff_size_, buff_capacity_, buff_size_, buff_); |
+ } |
+ |
+ // Try to fill the rest of buffer after current content. |
+ size_t avail = buff_capacity_ - buff_size_; |
+ int ret = fd_.Read(buff_ + buff_size_, avail); |
+ LLOG("%s: READ buff_size=%d buff_capacity=%d avail=%d ret=%d\n", |
+ __FUNCTION__, buff_size_, buff_capacity_, avail, ret); |
+ if (ret <= 0) { |
+ eof_ = true; |
+ ret = 0; |
+ } |
+ buff_size_ += static_cast<size_t>(ret); |
+ } |
+} |
+ |
+const char* LineReader::line() const { |
+ return buff_ + line_start_; |
+} |
+ |
+size_t LineReader::length() const { |
+ return line_len_; |
+} |
+ |
+} // namespace crazy |