/ src / client / linux / minidump_writer / line_reader.h
line_reader.h
  1  // Copyright 2009 Google LLC
  2  //
  3  // Redistribution and use in source and binary forms, with or without
  4  // modification, are permitted provided that the following conditions are
  5  // met:
  6  //
  7  //     * Redistributions of source code must retain the above copyright
  8  // notice, this list of conditions and the following disclaimer.
  9  //     * Redistributions in binary form must reproduce the above
 10  // copyright notice, this list of conditions and the following disclaimer
 11  // in the documentation and/or other materials provided with the
 12  // distribution.
 13  //     * Neither the name of Google LLC nor the names of its
 14  // contributors may be used to endorse or promote products derived from
 15  // this software without specific prior written permission.
 16  //
 17  // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 18  // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 19  // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 20  // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 21  // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 22  // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 23  // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 24  // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 25  // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 26  // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 27  // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 28  
 29  #ifndef CLIENT_LINUX_MINIDUMP_WRITER_LINE_READER_H_
 30  #define CLIENT_LINUX_MINIDUMP_WRITER_LINE_READER_H_
 31  
 32  #include <stdint.h>
 33  #include <assert.h>
 34  #include <string.h>
 35  
 36  #include "common/linux/linux_libc_support.h"
 37  #include "third_party/lss/linux_syscall_support.h"
 38  
 39  namespace google_breakpad {
 40  
 41  // A class for reading a file, line by line, without using fopen/fgets or other
 42  // functions which may allocate memory.
 43  class LineReader {
 44   public:
 45    LineReader(int fd)
 46        : fd_(fd),
 47          hit_eof_(false),
 48          buf_used_(0) {
 49    }
 50  
 51    // The maximum length of a line.
 52    static const size_t kMaxLineLen = 512;
 53  
 54    // Return the next line from the file.
 55    //   line: (output) a pointer to the start of the line. The line is NUL
 56    //     terminated.
 57    //   len: (output) the length of the line (not inc the NUL byte)
 58    //
 59    // Returns true iff successful (false on EOF).
 60    //
 61    // One must call |PopLine| after this function, otherwise you'll continue to
 62    // get the same line over and over.
 63    bool GetNextLine(const char** line, unsigned* len) {
 64      for (;;) {
 65        if (buf_used_ == 0 && hit_eof_)
 66          return false;
 67  
 68        for (unsigned i = 0; i < buf_used_; ++i) {
 69          if (buf_[i] == '\n' || buf_[i] == 0) {
 70            buf_[i] = 0;
 71            *len = i;
 72            *line = buf_;
 73            return true;
 74          }
 75        }
 76  
 77        if (buf_used_ == sizeof(buf_)) {
 78          // we scanned the whole buffer and didn't find an end-of-line marker.
 79          // This line is too long to process.
 80          return false;
 81        }
 82  
 83        // We didn't find any end-of-line terminators in the buffer. However, if
 84        // this is the last line in the file it might not have one:
 85        if (hit_eof_) {
 86          assert(buf_used_);
 87          // There's room for the NUL because of the buf_used_ == sizeof(buf_)
 88          // check above.
 89          buf_[buf_used_] = 0;
 90          *len = buf_used_;
 91          buf_used_ += 1;  // since we appended the NUL.
 92          *line = buf_;
 93          return true;
 94        }
 95  
 96        // Otherwise, we should pull in more data from the file
 97        const ssize_t n = sys_read(fd_, buf_ + buf_used_,
 98                                   sizeof(buf_) - buf_used_);
 99        if (n < 0) {
100          return false;
101        } else if (n == 0) {
102          hit_eof_ = true;
103        } else {
104          buf_used_ += n;
105        }
106  
107        // At this point, we have either set the hit_eof_ flag, or we have more
108        // data to process...
109      }
110    }
111  
112    void PopLine(unsigned len) {
113      // len doesn't include the NUL byte at the end.
114  
115      assert(buf_used_ >= len + 1);
116      buf_used_ -= len + 1;
117      my_memmove(buf_, buf_ + len + 1, buf_used_);
118    }
119  
120   private:
121    const int fd_;
122  
123    bool hit_eof_;
124    unsigned buf_used_;
125    char buf_[kMaxLineLen];
126  };
127  
128  }  // namespace google_breakpad
129  
130  #endif  // CLIENT_LINUX_MINIDUMP_WRITER_LINE_READER_H_