xref: /aosp_15_r20/external/google-breakpad/src/client/linux/minidump_writer/line_reader.h (revision 9712c20fc9bbfbac4935993a2ca0b3958c5adad2)
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:
LineReader(int fd)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.
GetNextLine(const char ** line,unsigned * len)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 
PopLine(unsigned len)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_
131