Move modules to ccan/ tools to tools/
[ccan] / tools / ccanlint / get_file_lines.c
1 #include "get_file_lines.h"
2 #include <talloc/talloc.h>
3 #include <string/string.h>
4 #include <noerr/noerr.h>
5 #include <unistd.h>
6 #include <sys/types.h>
7 #include <sys/stat.h>
8 #include <fcntl.h>
9 #include <err.h>
10 #include <dirent.h>
11
12 static void *grab_fd(const void *ctx, int fd)
13 {
14         int ret;
15         unsigned int max = 16384, size = 0;
16         char *buffer;
17
18         buffer = talloc_array(ctx, char, max+1);
19         while ((ret = read(fd, buffer + size, max - size)) > 0) {
20                 size += ret;
21                 if (size == max)
22                         buffer = talloc_realloc(ctx, buffer, char, max*=2 + 1);
23         }
24         if (ret < 0) {
25                 talloc_free(buffer);
26                 buffer = NULL;
27         } else
28                 buffer[size] = '\0';
29
30         return buffer;
31 }
32
33 /* This version adds one byte (for nul term) */
34 static void *grab_file(const void *ctx, const char *filename)
35 {
36         int fd;
37         char *buffer;
38
39         if (streq(filename, "-"))
40                 fd = dup(STDIN_FILENO);
41         else
42                 fd = open(filename, O_RDONLY, 0);
43
44         if (fd < 0)
45                 return NULL;
46
47         buffer = grab_fd(ctx, fd);
48         close_noerr(fd);
49         return buffer;
50 }
51
52 /* This is a dumb one which copies.  We could mangle instead. */
53 static char **split(const void *ctx, const char *text, const char *delims,
54                     unsigned int *nump)
55 {
56         char **lines = NULL;
57         unsigned int max = 64, num = 0;
58
59         lines = talloc_array(ctx, char *, max+1);
60
61         while (*text != '\0') {
62                 unsigned int len = strcspn(text, delims);
63                 lines[num] = talloc_array(lines, char, len + 1);
64                 memcpy(lines[num], text, len);
65                 lines[num][len] = '\0';
66                 text += len;
67                 text += strspn(text, delims);
68                 if (++num == max)
69                         lines = talloc_realloc(ctx, lines, char *, max*=2 + 1);
70         }
71         lines[num] = NULL;
72         if (nump)
73                 *nump = num;
74         return lines;
75 }
76
77 char **get_file_lines(void *ctx, const char *name, unsigned int *num_lines)
78 {
79         char *buffer = grab_file(ctx, name);
80
81         if (!buffer)
82                 err(1, "Getting file %s", name);
83
84         return split(buffer, buffer, "\n", num_lines);
85 }