1 /* $Id: qio.c 6943 2004-06-10 22:20:24Z hkehoe $
5 ** A set of routines optimized for reading through files line by line.
6 ** This package uses internal buffering like stdio, but is even more
7 ** aggressive about its buffering. The basic read call reads a single line
8 ** and returns the whole line, provided that it can fit in the buffer.
20 /* A reasonable default buffer size to use. */
21 #define QIO_BUFFERSIZE 8192
24 ** Given a file descriptor, return a reasonable buffer size to use for that
25 ** file. Uses st_blksize if available and reasonable, QIO_BUFFERSIZE
31 size_t size = QIO_BUFFERSIZE;
36 /* The Solaris 2.6 man page says that st_blksize is not defined for
37 block or character special devices (and could contain garbage), so
38 only use this value for regular files. */
39 if (fstat(fd, &st) == 0 && S_ISREG(st.st_mode)) {
41 if (size > (4 * QIO_BUFFERSIZE) || size == 0)
42 size = QIO_BUFFERSIZE;
44 while(size < QIO_BUFFERSIZE)
45 size += st.st_blksize;
47 #endif /* HAVE_ST_BLKSIZE */
54 ** Open a quick file from a descriptor.
57 QIOfdopen(const int fd)
61 qp = xmalloc(sizeof(*qp));
64 qp->_size = buffer_size(fd);
65 qp->_buffer = xmalloc(qp->_size);
66 qp->_start = qp->_buffer;
67 qp->_end = qp->_buffer;
76 ** Open a quick file from a file name.
79 QIOopen(const char *name)
83 fd = open(name, O_RDONLY);
91 ** Close an open quick file.
94 QIOclose(QIOSTATE *qp)
103 ** Rewind a quick file. Reads the first buffer full of data automatically,
104 ** anticipating the first read from the file. Returns -1 on error, 0 on
108 QIOrewind(QIOSTATE *qp)
112 if (lseek(qp->_fd, 0, SEEK_SET) < 0)
114 nread = read(qp->_fd, qp->_buffer, qp->_size);
118 qp->_start = qp->_buffer;
119 qp->_end = qp->_buffer + nread;
125 ** Get the next newline-terminated line from a quick file, replacing the
126 ** newline with a nul. Returns a pointer to that line on success and NULL
127 ** on failure or end of file, with _flag set appropriately.
130 QIOread(QIOSTATE *qp)
136 /* Loop until we get a result or fill the buffer. */
139 nleft = qp->_end - qp->_start;
141 /* If nleft <= 0, the buffer currently contains no data that hasn't
142 previously been returned by QIOread, so we can overwrite the
143 buffer with new data. Otherwise, first check the existing data
144 to see if we have a full line. */
146 qp->_start = qp->_buffer;
147 qp->_end = qp->_buffer;
149 p = memchr(qp->_start, '\n', nleft);
152 qp->_length = p - qp->_start;
155 return (qp->_flag == QIO_long) ? NULL : line;
158 /* Not there. See if our buffer is full. If so, tag as having
159 seen too long of a line. This will cause us to keep reading
160 as normal until we finally see the end of a line and then
162 if (nleft >= qp->_size) {
163 qp->_flag = QIO_long;
164 qp->_start = qp->_end;
168 /* We need to read more data. If there's read data in buffer,
169 then move the unread data down to the beginning of the buffer
171 if (qp->_start > qp->_buffer) {
173 memmove(qp->_buffer, qp->_start, nleft);
174 qp->_start = qp->_buffer;
175 qp->_end = qp->_buffer + nleft;
179 /* Read in some more data, and then let the loop try to find the
180 newline again or discover that the line is too long. */
182 nread = read(qp->_fd, qp->_end, qp->_size - nleft);
183 } while (nread == -1 && errno == EINTR);
186 qp->_flag = QIO_error;