]> asedeno.scripts.mit.edu Git - git.git/blob - builtin-stripspace.c
Replace all read_fd use with strbuf_read, and get rid of it.
[git.git] / builtin-stripspace.c
1 #include "builtin.h"
2 #include "cache.h"
3 #include "strbuf.h"
4
5 /*
6  * Returns the length of a line, without trailing spaces.
7  *
8  * If the line ends with newline, it will be removed too.
9  */
10 static size_t cleanup(char *line, size_t len)
11 {
12         if (len) {
13                 if (line[len - 1] == '\n')
14                         len--;
15
16                 while (len) {
17                         unsigned char c = line[len - 1];
18                         if (!isspace(c))
19                                 break;
20                         len--;
21                 }
22         }
23         return len;
24 }
25
26 /*
27  * Remove empty lines from the beginning and end
28  * and also trailing spaces from every line.
29  *
30  * Note that the buffer will not be NUL-terminated.
31  *
32  * Turn multiple consecutive empty lines between paragraphs
33  * into just one empty line.
34  *
35  * If the input has only empty lines and spaces,
36  * no output will be produced.
37  *
38  * If last line has a newline at the end, it will be removed.
39  *
40  * Enable skip_comments to skip every line starting with "#".
41  */
42 size_t stripspace(char *buffer, size_t length, int skip_comments)
43 {
44         int empties = -1;
45         size_t i, j, len, newlen;
46         char *eol;
47
48         for (i = j = 0; i < length; i += len, j += newlen) {
49                 eol = memchr(buffer + i, '\n', length - i);
50                 len = eol ? eol - (buffer + i) + 1 : length - i;
51
52                 if (skip_comments && len && buffer[i] == '#') {
53                         newlen = 0;
54                         continue;
55                 }
56                 newlen = cleanup(buffer + i, len);
57
58                 /* Not just an empty line? */
59                 if (newlen) {
60                         if (empties != -1)
61                                 buffer[j++] = '\n';
62                         if (empties > 0)
63                                 buffer[j++] = '\n';
64                         empties = 0;
65                         memmove(buffer + j, buffer + i, newlen);
66                         continue;
67                 }
68                 if (empties < 0)
69                         continue;
70                 empties++;
71         }
72
73         return j;
74 }
75
76 int cmd_stripspace(int argc, const char **argv, const char *prefix)
77 {
78         struct strbuf buf;
79         int strip_comments = 0;
80
81         if (argc > 1 && (!strcmp(argv[1], "-s") ||
82                                 !strcmp(argv[1], "--strip-comments")))
83                 strip_comments = 1;
84
85         strbuf_init(&buf, 0);
86         if (strbuf_read(&buf, 0, 1024) < 0)
87                 die("could not read the input");
88
89         strbuf_setlen(&buf, stripspace(buf.buf, buf.len, strip_comments));
90         if (buf.len)
91                 strbuf_addch(&buf, '\n');
92
93         write_or_die(1, buf.buf, buf.len);
94         strbuf_release(&buf);
95         return 0;
96 }