for-each-ref: Do not lookup objects when they will not be used
[gitweb.git] / color.c
diff --git a/color.c b/color.c
index fc0b72ad59b13e4bd86372e5e81b4f400c99d26e..62977f4808ae339fdfe797e16b4eb28dc6abb85d 100644 (file)
--- a/color.c
+++ b/color.c
@@ -1,8 +1,6 @@
 #include "cache.h"
 #include "color.h"
 
-#define COLOR_RESET "\033[m"
-
 int git_use_color_default = 0;
 
 static int parse_color(const char *name, int len)
@@ -40,30 +38,41 @@ static int parse_attr(const char *name, int len)
 }
 
 void color_parse(const char *value, const char *var, char *dst)
+{
+       color_parse_mem(value, strlen(value), var, dst);
+}
+
+void color_parse_mem(const char *value, int value_len, const char *var,
+               char *dst)
 {
        const char *ptr = value;
+       int len = value_len;
        int attr = -1;
        int fg = -2;
        int bg = -2;
 
-       if (!strcasecmp(value, "reset")) {
-               strcpy(dst, "\033[m");
+       if (!strncasecmp(value, "reset", len)) {
+               strcpy(dst, GIT_COLOR_RESET);
                return;
        }
 
        /* [fg [bg]] [attr] */
-       while (*ptr) {
+       while (len > 0) {
                const char *word = ptr;
-               int val, len = 0;
+               int val, wordlen = 0;
 
-               while (word[len] && !isspace(word[len]))
-                       len++;
+               while (len > 0 && !isspace(word[wordlen])) {
+                       wordlen++;
+                       len--;
+               }
 
-               ptr = word + len;
-               while (*ptr && isspace(*ptr))
+               ptr = word + wordlen;
+               while (len > 0 && isspace(*ptr)) {
                        ptr++;
+                       len--;
+               }
 
-               val = parse_color(word, len);
+               val = parse_color(word, wordlen);
                if (val >= -1) {
                        if (fg == -2) {
                                fg = val;
@@ -75,7 +84,7 @@ void color_parse(const char *value, const char *var, char *dst)
                        }
                        goto bad;
                }
-               val = parse_attr(word, len);
+               val = parse_attr(word, wordlen);
                if (val < 0 || attr != -1)
                        goto bad;
                attr = val;
@@ -115,7 +124,7 @@ void color_parse(const char *value, const char *var, char *dst)
        *dst = 0;
        return;
 bad:
-       die("bad config value '%s' for variable '%s'", value, var);
+       die("bad color value '%.*s' for variable '%s'", value_len, value, var);
 }
 
 int git_config_colorbool(const char *var, const char *value, int stdout_is_tty)
@@ -164,7 +173,7 @@ static int color_vfprintf(FILE *fp, const char *color, const char *fmt,
                r += fprintf(fp, "%s", color);
        r += vfprintf(fp, fmt, args);
        if (*color)
-               r += fprintf(fp, "%s", COLOR_RESET);
+               r += fprintf(fp, "%s", GIT_COLOR_RESET);
        if (trail)
                r += fprintf(fp, "%s", trail);
        return r;
@@ -191,3 +200,31 @@ int color_fprintf_ln(FILE *fp, const char *color, const char *fmt, ...)
        va_end(args);
        return r;
 }
+
+/*
+ * This function splits the buffer by newlines and colors the lines individually.
+ *
+ * Returns 0 on success.
+ */
+int color_fwrite_lines(FILE *fp, const char *color,
+               size_t count, const char *buf)
+{
+       if (!*color)
+               return fwrite(buf, count, 1, fp) != 1;
+       while (count) {
+               char *p = memchr(buf, '\n', count);
+               if (p != buf && (fputs(color, fp) < 0 ||
+                               fwrite(buf, p ? p - buf : count, 1, fp) != 1 ||
+                               fputs(GIT_COLOR_RESET, fp) < 0))
+                       return -1;
+               if (!p)
+                       return 0;
+               if (fputc('\n', fp) < 0)
+                       return -1;
+               count -= p + 1 - buf;
+               buf = p + 1;
+       }
+       return 0;
+}
+
+