builtin-stripspace.con commit Replace all read_fd use with strbuf_read, and get rid of it. (fd17f5b)
   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 */
  10static 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 */
  42size_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
  76int 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}