1/*
2 * Copyright 2013-present Facebook, Inc.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include <folly/experimental/symbolizer/LineReader.h>
18
19#include <cstring>
20
21#include <folly/FileUtil.h>
22
23namespace folly {
24namespace symbolizer {
25
26LineReader::LineReader(int fd, char* buf, size_t bufSize)
27 : fd_(fd),
28 buf_(buf),
29 bufEnd_(buf_ + bufSize),
30 bol_(buf),
31 eol_(buf),
32 end_(buf),
33 state_(kReading) {}
34
35LineReader::State LineReader::readLine(StringPiece& line) {
36 bol_ = eol_; // Start past what we already returned
37 for (;;) {
38 // Search for newline
39 char* newline = static_cast<char*>(memchr(eol_, '\n', end_ - eol_));
40 if (newline) {
41 eol_ = newline + 1;
42 break;
43 } else if (state_ != kReading || (bol_ == buf_ && end_ == bufEnd_)) {
44 // If the buffer is full with one line (line too long), or we're
45 // at the end of the file, return what we have.
46 eol_ = end_;
47 break;
48 }
49
50 // We don't have a full line in the buffer, but we have room to read.
51 // Move to the beginning of the buffer.
52 memmove(buf_, eol_, end_ - eol_);
53 end_ -= (eol_ - buf_);
54 bol_ = buf_;
55 eol_ = end_;
56
57 // Refill
58 ssize_t available = bufEnd_ - end_;
59 ssize_t n = readFull(fd_, end_, available);
60 if (n < 0) {
61 state_ = kError;
62 n = 0;
63 } else if (n < available) {
64 state_ = kEof;
65 }
66 end_ += n;
67 }
68
69 line.assign(bol_, eol_);
70 return eol_ != bol_ ? kReading : state_;
71}
72} // namespace symbolizer
73} // namespace folly
74