db_updater: Put parentheses back
[merlin.git] / lparse.c
blob8941ebca89899044ff891dfe7c5c727f2c96d64f
1 #define _GNU_SOURCE 1
2 #include <stdio.h>
3 #include <stdlib.h>
4 #include <unistd.h>
5 #include <string.h>
6 #include <errno.h>
7 #include <sys/types.h>
8 #include <sys/stat.h>
9 #include <fcntl.h>
10 #include "compat.h"
11 #include "lparse.h"
13 static char *buf;
14 #define MAX_BUF ((512 * 1024) - 1)
16 int lparse_fd(int fd, uint64_t size, int (*parse)(char *, uint))
18 uint64_t tot_rd = 0;
20 if (!buf && !(buf = calloc(1, MAX_BUF + 1)))
21 return -1;
23 while (tot_rd < size) {
24 char *next, *cur;
25 int blkparsed, bytes_rd;
27 bytes_rd = read(fd, buf, MAX_BUF < size ? MAX_BUF : size);
28 if (bytes_rd < 0)
29 return -1;
31 if (tot_rd + bytes_rd < size) {
32 /* rewind the file to the last found newline */
33 while (buf[bytes_rd - 1] != '\n')
34 bytes_rd--;
35 lseek(fd, tot_rd + bytes_rd, SEEK_SET);
37 tot_rd += bytes_rd;
39 /* set a sentinel for memchr() */
40 buf[bytes_rd] = '\n';
42 cur = buf;
43 for (blkparsed = 0; blkparsed < bytes_rd; cur = next + 1) {
44 uint len;
45 next = memchr(cur, '\n', bytes_rd + 1 - blkparsed);
46 len = next - cur;
47 blkparsed += len + 1;
49 cur[len] = '\0';
50 parse(cur, len);
54 return 0;
57 int lparse_rev_fd(int fd, uint64_t size, int (*parse)(char *, uint))
59 uint64_t tot_rd = 0, parsed = 0, reads = 0;
61 if (!buf && !(buf = calloc(1, MAX_BUF + 1)))
62 return -1;
64 while (tot_rd < size) {
65 char *cur, *first, *eol, *last;
66 int blkparsed, bytes_rd;
67 size_t to_read;
70 * First we figure out where to start reading
71 * and how much to read. Then we lseek() to that
72 * position and actually read it in (works)
74 if (tot_rd + MAX_BUF < size) {
75 to_read = MAX_BUF;
76 } else {
77 to_read = size - tot_rd;
79 lseek(fd, size - tot_rd - to_read, SEEK_SET);
80 reads++;
81 bytes_rd = read(fd, buf, to_read);
82 if (bytes_rd < 0)
83 return -1;
85 if (tot_rd + bytes_rd < size) {
88 * set 'first' to just after first newline or,
89 * failing that, to the start of the buffer itself
91 first = memchr(buf, '\n', bytes_rd);
92 if (!first)
93 first = buf;
94 else
95 first++;
97 /* remember the position of the first found newline */
98 bytes_rd -= first - buf;
99 } else {
100 first = buf;
102 tot_rd += bytes_rd;
105 * if the buffer we just read ends with a newline, we must
106 * discard it from the first round of parsing, or we'll add
107 * one line for each time we read.
109 if (first[bytes_rd - 1] == '\n')
110 --bytes_rd;
112 eol = last = first + bytes_rd;
113 for (blkparsed = 0; blkparsed < bytes_rd; cur = eol - 1) {
114 uint len;
115 char *line;
118 * set 'cur' to first newline befor 'eol', and set
119 * 'line' to first char after it
121 cur = memrchr(first, '\n', bytes_rd - blkparsed);
122 if (!cur) {
123 line = cur = first;
124 } else {
125 line = cur + 1;
128 len = eol - line;
129 blkparsed += len + 1;
131 *eol = '\0';
132 parse(line, len);
133 eol = cur;
135 parsed += bytes_rd;
138 return 0;
141 int lparse_path_real(int rev, const char *path, uint64_t size, int (*parse)(char *, uint))
143 int fd, result;
145 /* zero size files are never interesting */
146 if (!size)
147 return 0;
149 if ((fd = open(path, O_RDONLY)) < 0)
150 return -1;
152 if (rev)
153 result = lparse_rev_fd(fd, size, parse);
154 else
155 result = lparse_fd(fd, size, parse);
157 close(fd);
159 return result;