make update-server-info more robust
[gitweb.git] / strbuf.c
index 05d0693eba1eba4e2f21057388368c0890e668fe..33018d847f08424211c02cff8002680f5a2f02e9 100644 (file)
--- a/strbuf.c
+++ b/strbuf.c
@@ -1,22 +1,14 @@
 #include "cache.h"
 #include "refs.h"
+#include "utf8.h"
 
-int prefixcmp(const char *str, const char *prefix)
+int starts_with(const char *str, const char *prefix)
 {
        for (; ; str++, prefix++)
                if (!*prefix)
-                       return 0;
+                       return 1;
                else if (*str != *prefix)
-                       return (unsigned char)*prefix - (unsigned char)*str;
-}
-
-int suffixcmp(const char *str, const char *suffix)
-{
-       int len = strlen(str), suflen = strlen(suffix);
-       if (len < suflen)
-               return -1;
-       else
-               return strcmp(str + len - suflen, suffix);
+                       return 0;
 }
 
 /*
@@ -78,15 +70,8 @@ void strbuf_grow(struct strbuf *sb, size_t extra)
 
 void strbuf_trim(struct strbuf *sb)
 {
-       char *b = sb->buf;
-       while (sb->len > 0 && isspace((unsigned char)sb->buf[sb->len - 1]))
-               sb->len--;
-       while (sb->len > 0 && isspace(*b)) {
-               b++;
-               sb->len--;
-       }
-       memmove(sb->buf, b, sb->len);
-       sb->buf[sb->len] = '\0';
+       strbuf_rtrim(sb);
+       strbuf_ltrim(sb);
 }
 void strbuf_rtrim(struct strbuf *sb)
 {
@@ -106,6 +91,29 @@ void strbuf_ltrim(struct strbuf *sb)
        sb->buf[sb->len] = '\0';
 }
 
+int strbuf_reencode(struct strbuf *sb, const char *from, const char *to)
+{
+       char *out;
+       int len;
+
+       if (same_encoding(from, to))
+               return 0;
+
+       out = reencode_string_len(sb->buf, sb->len, to, from, &len);
+       if (!out)
+               return -1;
+
+       strbuf_attach(sb, out, len, len);
+       return 0;
+}
+
+void strbuf_tolower(struct strbuf *sb)
+{
+       char *p = sb->buf, *end = sb->buf + sb->len;
+       for (; p < end; p++)
+               *p = tolower(*p);
+}
+
 struct strbuf **strbuf_split_buf(const char *str, size_t slen,
                                 int terminator, int max)
 {
@@ -204,6 +212,54 @@ void strbuf_addf(struct strbuf *sb, const char *fmt, ...)
        va_end(ap);
 }
 
+static void add_lines(struct strbuf *out,
+                       const char *prefix1,
+                       const char *prefix2,
+                       const char *buf, size_t size)
+{
+       while (size) {
+               const char *prefix;
+               const char *next = memchr(buf, '\n', size);
+               next = next ? (next + 1) : (buf + size);
+
+               prefix = (prefix2 && buf[0] == '\n') ? prefix2 : prefix1;
+               strbuf_addstr(out, prefix);
+               strbuf_add(out, buf, next - buf);
+               size -= next - buf;
+               buf = next;
+       }
+       strbuf_complete_line(out);
+}
+
+void strbuf_add_commented_lines(struct strbuf *out, const char *buf, size_t size)
+{
+       static char prefix1[3];
+       static char prefix2[2];
+
+       if (prefix1[0] != comment_line_char) {
+               sprintf(prefix1, "%c ", comment_line_char);
+               sprintf(prefix2, "%c", comment_line_char);
+       }
+       add_lines(out, prefix1, prefix2, buf, size);
+}
+
+void strbuf_commented_addf(struct strbuf *sb, const char *fmt, ...)
+{
+       va_list params;
+       struct strbuf buf = STRBUF_INIT;
+       int incomplete_line = sb->len && sb->buf[sb->len - 1] != '\n';
+
+       va_start(params, fmt);
+       strbuf_vaddf(&buf, fmt, params);
+       va_end(params);
+
+       strbuf_add_commented_lines(sb, buf.buf, buf.len);
+       if (incomplete_line)
+               sb->buf[--sb->len] = '\0';
+
+       strbuf_release(&buf);
+}
+
 void strbuf_vaddf(struct strbuf *sb, const char *fmt, va_list ap)
 {
        int len;
@@ -414,15 +470,33 @@ int strbuf_read_file(struct strbuf *sb, const char *path, size_t hint)
 void strbuf_add_lines(struct strbuf *out, const char *prefix,
                      const char *buf, size_t size)
 {
-       while (size) {
-               const char *next = memchr(buf, '\n', size);
-               next = next ? (next + 1) : (buf + size);
-               strbuf_addstr(out, prefix);
-               strbuf_add(out, buf, next - buf);
-               size -= next - buf;
-               buf = next;
+       add_lines(out, prefix, NULL, buf, size);
+}
+
+void strbuf_addstr_xml_quoted(struct strbuf *buf, const char *s)
+{
+       while (*s) {
+               size_t len = strcspn(s, "\"<>&");
+               strbuf_add(buf, s, len);
+               s += len;
+               switch (*s) {
+               case '"':
+                       strbuf_addstr(buf, "&quot;");
+                       break;
+               case '<':
+                       strbuf_addstr(buf, "&lt;");
+                       break;
+               case '>':
+                       strbuf_addstr(buf, "&gt;");
+                       break;
+               case '&':
+                       strbuf_addstr(buf, "&amp;");
+                       break;
+               case 0:
+                       return;
+               }
+               s++;
        }
-       strbuf_complete_line(out);
 }
 
 static int is_rfc3986_reserved(char ch)
@@ -462,6 +536,25 @@ void strbuf_addstr_urlencode(struct strbuf *sb, const char *s,
        strbuf_add_urlencode(sb, s, strlen(s), reserved);
 }
 
+void strbuf_humanise_bytes(struct strbuf *buf, off_t bytes)
+{
+       if (bytes > 1 << 30) {
+               strbuf_addf(buf, "%u.%2.2u GiB",
+                           (int)(bytes >> 30),
+                           (int)(bytes & ((1 << 30) - 1)) / 10737419);
+       } else if (bytes > 1 << 20) {
+               int x = bytes + 5243;  /* for rounding */
+               strbuf_addf(buf, "%u.%2.2u MiB",
+                           x >> 20, ((x & ((1 << 20) - 1)) * 100) >> 20);
+       } else if (bytes > 1 << 10) {
+               int x = bytes + 5;  /* for rounding */
+               strbuf_addf(buf, "%u.%2.2u KiB",
+                           x >> 10, ((x & ((1 << 10) - 1)) * 100) >> 10);
+       } else {
+               strbuf_addf(buf, "%u bytes", (int)bytes);
+       }
+}
+
 int printf_ln(const char *fmt, ...)
 {
        int ret;
@@ -485,3 +578,35 @@ int fprintf_ln(FILE *fp, const char *fmt, ...)
                return -1;
        return ret + 1;
 }
+
+char *xstrdup_tolower(const char *string)
+{
+       char *result;
+       size_t len, i;
+
+       len = strlen(string);
+       result = xmalloc(len + 1);
+       for (i = 0; i < len; i++)
+               result[i] = tolower(string[i]);
+       result[i] = '\0';
+       return result;
+}
+
+char *xstrvfmt(const char *fmt, va_list ap)
+{
+       struct strbuf buf = STRBUF_INIT;
+       strbuf_vaddf(&buf, fmt, ap);
+       return strbuf_detach(&buf, NULL);
+}
+
+char *xstrfmt(const char *fmt, ...)
+{
+       va_list ap;
+       char *ret;
+
+       va_start(ap, fmt);
+       ret = xstrvfmt(fmt, ap);
+       va_end(ap);
+
+       return ret;
+}