-
Notifications
You must be signed in to change notification settings - Fork 0
/
readfile.c
97 lines (82 loc) · 1.66 KB
/
readfile.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
#define _WITH_GETLINE /* for FreeBSD */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include "samlib.h"
#if defined(WIN32)
#define GETLINE_INCREMENT 128
/* Simple getline implementation */
int getline(char **line, int *n, FILE *fp)
{
int ch, i = 0;
while (1) {
if (i >= *n - 1) {
char *p = realloc(*line, *n + GETLINE_INCREMENT);
if (!p)
return EOF;
*line = p;
*n += GETLINE_INCREMENT;
}
ch = fgetc(fp);
if (ch == EOF) {
if (i == 0)
return EOF;
*(*line + i) = 0;
return i;
}
*(*line + i++) = ch;
if (ch == '\n') {
*(*line + i) = 0;
return 1;
}
}
}
#endif
/* Read a file line at a time calling line_func() for each
* line. Removes the NL from the line. If line_func() returns
* non-zero, it will stop reading the file and return 1.
*
* If path is NULL, reads input from stdin.
*
* Returns 0 on success, -1 on file or memory error, or 1 if
* line_func() returns non-zero.
*/
int readfile(int (*line_func)(char *line, void *data), void *data,
const char *path, unsigned flags)
{
FILE *fp = path ? fopen(path, "rb") : stdin;
if (!fp)
return -1;
char *p, *line = NULL;
size_t len = 0;
int rc = 0;
if (!line_func) {
errno = EINVAL;
return -1;
}
while (getline(&line, &len, fp) != EOF) {
if ((p = strrchr(line, '\n')))
*p = 0;
if (flags & RF_IGNORE_EMPTY) {
for (p = line; isspace(*p); ++p) ;
if (*p == 0)
continue;
}
if (flags & RF_IGNORE_COMMENTS) {
if (*line == '#')
continue;
}
if (line_func(line, data)) {
rc = 1;
goto closeit;
}
}
if (!feof(fp))
rc = -1;
closeit:
free(line);
if (path && fclose(fp))
return -1;
return rc;
}