folly copyright 2015 -> copyright 2016
[folly.git] / folly / experimental / symbolizer / LineReader.cpp
1 /*
2  * Copyright 2016 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
23 namespace folly { namespace symbolizer {
24
25 LineReader::LineReader(int fd, char* buf, size_t bufSize)
26   : fd_(fd),
27     buf_(buf),
28     bufEnd_(buf_ + bufSize),
29     bol_(buf),
30     eol_(buf),
31     end_(buf),
32     state_(kReading) {
33 }
34
35 LineReader::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
73 }}  // namespaces