From 4acfd1b799acf43642a28a22cc794266c25129ef Mon Sep 17 00:00:00 2001 From: Pierre Habouzit Date: Mon, 10 Sep 2007 12:35:05 +0200 Subject: Change semantics of interpolate to work like snprintf. Also fix many off-by-ones and a useless memset. Signed-off-by: Pierre Habouzit Signed-off-by: Junio C Hamano --- commit.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) (limited to 'commit.c') diff --git a/commit.c b/commit.c index 99f65cee0e..25781cc833 100644 --- a/commit.c +++ b/commit.c @@ -923,15 +923,14 @@ long format_commit_message(const struct commit *commit, const void *format, do { char *buf = *buf_p; - unsigned long space = *space_p; + unsigned long len; - space = interpolate(buf, space, format, + len = interpolate(buf, *space_p, format, table, ARRAY_SIZE(table)); - if (!space) + if (len < *space_p) break; - buf = xrealloc(buf, space); + ALLOC_GROW(buf, len + 1, *space_p); *buf_p = buf; - *space_p = space; } while (1); interp_clear_table(table, ARRAY_SIZE(table)); -- cgit v1.2.3 From 674d1727305211f7ade4ade70440220f74f55162 Mon Sep 17 00:00:00 2001 From: Pierre Habouzit Date: Mon, 10 Sep 2007 12:35:06 +0200 Subject: Rework pretty_print_commit to use strbufs instead of custom buffers. Also remove the "len" parameter, as: (1) it was used as a max boundary, and every caller used ~0u (2) we check for final NUL no matter what, so it doesn't help for speed. As a result most of the pp_* function takes 3 arguments less, and we need a lot less local variables, this makes the code way more readable, and easier to extend if needed. This patch also fixes some spacing and cosmetic issues. This patch also fixes (as a side effect) a memory leak intoruced in builtin-archive.c at commit df4a394f (fmt was xmalloc'ed and not free'd) Signed-off-by: Pierre Habouzit Signed-off-by: Junio C Hamano --- builtin-archive.c | 39 +++--- builtin-branch.c | 15 ++- builtin-log.c | 12 +- builtin-rev-list.c | 13 +- builtin-show-branch.c | 13 +- commit.c | 333 +++++++++++++++++++------------------------------- commit.h | 9 +- log-tree.c | 56 +++------ 8 files changed, 191 insertions(+), 299 deletions(-) (limited to 'commit.c') diff --git a/builtin-archive.c b/builtin-archive.c index a90c65ce54..b50d5ad196 100644 --- a/builtin-archive.c +++ b/builtin-archive.c @@ -84,14 +84,16 @@ static int run_remote_archiver(const char *remote, int argc, static void *format_subst(const struct commit *commit, const char *format, unsigned long *sizep) { - unsigned long len = *sizep, result_len = 0; + unsigned long len = *sizep; const char *a = format; - char *result = NULL; + struct strbuf result; + struct strbuf fmt; + + strbuf_init(&result, 0); + strbuf_init(&fmt, 0); for (;;) { const char *b, *c; - char *fmt, *formatted = NULL; - unsigned long a_len, fmt_len, formatted_len, allocated = 0; b = memmem(a, len, "$Format:", 8); if (!b || a + len < b + 9) @@ -100,32 +102,23 @@ static void *format_subst(const struct commit *commit, const char *format, if (!c) break; - a_len = b - a; - fmt_len = c - b - 8; - fmt = xmalloc(fmt_len + 1); - memcpy(fmt, b + 8, fmt_len); - fmt[fmt_len] = '\0'; - - formatted_len = format_commit_message(commit, fmt, &formatted, - &allocated); - free(fmt); - result = xrealloc(result, result_len + a_len + formatted_len); - memcpy(result + result_len, a, a_len); - memcpy(result + result_len + a_len, formatted, formatted_len); - result_len += a_len + formatted_len; + strbuf_reset(&fmt); + strbuf_add(&fmt, b + 8, c - b - 8); + + strbuf_add(&result, a, b - a); + format_commit_message(commit, fmt.buf, &result); len -= c + 1 - a; a = c + 1; } - if (result && len) { - result = xrealloc(result, result_len + len); - memcpy(result + result_len, a, len); - result_len += len; + if (result.len && len) { + strbuf_add(&result, a, len); } - *sizep = result_len; + *sizep = result.len; - return result; + strbuf_release(&fmt); + return strbuf_detach(&result); } static void *convert_to_archive(const char *path, diff --git a/builtin-branch.c b/builtin-branch.c index 5f5c1823cb..3da8b55b8f 100644 --- a/builtin-branch.c +++ b/builtin-branch.c @@ -268,23 +268,22 @@ static void print_ref_item(struct ref_item *item, int maxwidth, int verbose, } if (verbose) { - char *subject = NULL; - unsigned long subject_len = 0; + struct strbuf subject; const char *sub = " **** invalid ref ****"; + strbuf_init(&subject, 0); + commit = lookup_commit(item->sha1); if (commit && !parse_commit(commit)) { - pretty_print_commit(CMIT_FMT_ONELINE, commit, ~0, - &subject, &subject_len, 0, - NULL, NULL, 0); - sub = subject; + pretty_print_commit(CMIT_FMT_ONELINE, commit, + &subject, 0, NULL, NULL, 0); + sub = subject.buf; } printf("%c %s%-*s%s %s %s\n", c, branch_get_color(color), maxwidth, item->name, branch_get_color(COLOR_BRANCH_RESET), find_unique_abbrev(item->sha1, abbrev), sub); - if (subject) - free(subject); + strbuf_release(&subject); } else { printf("%c %s%s%s\n", c, branch_get_color(color), item->name, branch_get_color(COLOR_BRANCH_RESET)); diff --git a/builtin-log.c b/builtin-log.c index fa81c25920..e1d3e7d74b 100644 --- a/builtin-log.c +++ b/builtin-log.c @@ -763,13 +763,13 @@ int cmd_cherry(int argc, const char **argv, const char *prefix) sign = '-'; if (verbose) { - char *buf = NULL; - unsigned long buflen = 0; - pretty_print_commit(CMIT_FMT_ONELINE, commit, ~0, - &buf, &buflen, 0, NULL, NULL, 0); + struct strbuf buf; + strbuf_init(&buf, 0); + pretty_print_commit(CMIT_FMT_ONELINE, commit, + &buf, 0, NULL, NULL, 0); printf("%c %s %s\n", sign, - sha1_to_hex(commit->object.sha1), buf); - free(buf); + sha1_to_hex(commit->object.sha1), buf.buf); + strbuf_release(&buf); } else { printf("%c %s\n", sign, diff --git a/builtin-rev-list.c b/builtin-rev-list.c index ac551d59f3..4fd4b6bec1 100644 --- a/builtin-rev-list.c +++ b/builtin-rev-list.c @@ -80,13 +80,12 @@ static void show_commit(struct commit *commit) putchar('\n'); if (revs.verbose_header) { - char *buf = NULL; - unsigned long buflen = 0; - pretty_print_commit(revs.commit_format, commit, ~0, - &buf, &buflen, - revs.abbrev, NULL, NULL, revs.date_mode); - printf("%s%c", buf, hdr_termination); - free(buf); + struct strbuf buf; + strbuf_init(&buf, 0); + pretty_print_commit(revs.commit_format, commit, + &buf, revs.abbrev, NULL, NULL, revs.date_mode); + printf("%s%c", buf.buf, hdr_termination); + strbuf_release(&buf); } maybe_flush_or_die(stdout, "stdout"); if (commit->parents) { diff --git a/builtin-show-branch.c b/builtin-show-branch.c index 4fa87f6081..07a0c2316b 100644 --- a/builtin-show-branch.c +++ b/builtin-show-branch.c @@ -259,16 +259,15 @@ static void join_revs(struct commit_list **list_p, static void show_one_commit(struct commit *commit, int no_name) { - char *pretty = NULL; + struct strbuf pretty; const char *pretty_str = "(unavailable)"; - unsigned long pretty_len = 0; struct commit_name *name = commit->util; + strbuf_init(&pretty, 0); if (commit->object.parsed) { - pretty_print_commit(CMIT_FMT_ONELINE, commit, ~0, - &pretty, &pretty_len, - 0, NULL, NULL, 0); - pretty_str = pretty; + pretty_print_commit(CMIT_FMT_ONELINE, commit, + &pretty, 0, NULL, NULL, 0); + pretty_str = pretty.buf; } if (!prefixcmp(pretty_str, "[PATCH] ")) pretty_str += 8; @@ -289,7 +288,7 @@ static void show_one_commit(struct commit *commit, int no_name) find_unique_abbrev(commit->object.sha1, 7)); } puts(pretty_str); - free(pretty); + strbuf_release(&pretty); } static char *ref_name[MAX_REVS + 1]; diff --git a/commit.c b/commit.c index 25781cc833..6602e2c72f 100644 --- a/commit.c +++ b/commit.c @@ -458,11 +458,11 @@ void clear_commit_marks(struct commit *commit, unsigned int mark) /* * Generic support for pretty-printing the header */ -static int get_one_line(const char *msg, unsigned long len) +static int get_one_line(const char *msg) { int ret = 0; - while (len--) { + for (;;) { char c = *msg++; if (!c) break; @@ -485,31 +485,24 @@ static int is_rfc2047_special(char ch) return (non_ascii(ch) || (ch == '=') || (ch == '?') || (ch == '_')); } -static int add_rfc2047(char *buf, const char *line, int len, +static void add_rfc2047(struct strbuf *sb, const char *line, int len, const char *encoding) { - char *bp = buf; - int i, needquote; - char q_encoding[128]; - const char *q_encoding_fmt = "=?%s?q?"; + int i, last; - for (i = needquote = 0; !needquote && i < len; i++) { + for (i = 0; i < len; i++) { int ch = line[i]; if (non_ascii(ch)) - needquote++; - if ((i + 1 < len) && - (ch == '=' && line[i+1] == '?')) - needquote++; + goto needquote; + if ((i + 1 < len) && (ch == '=' && line[i+1] == '?')) + goto needquote; } - if (!needquote) - return sprintf(buf, "%.*s", len, line); - - i = snprintf(q_encoding, sizeof(q_encoding), q_encoding_fmt, encoding); - if (sizeof(q_encoding) < i) - die("Insanely long encoding name %s", encoding); - memcpy(bp, q_encoding, i); - bp += i; - for (i = 0; i < len; i++) { + strbuf_add(sb, line, len); + return; + +needquote: + strbuf_addf(sb, "=?%s?q?", encoding); + for (i = last = 0; i < len; i++) { unsigned ch = line[i] & 0xFF; /* * We encode ' ' using '=20' even though rfc2047 @@ -518,15 +511,13 @@ static int add_rfc2047(char *buf, const char *line, int len, * leave the underscore in place. */ if (is_rfc2047_special(ch) || ch == ' ') { - sprintf(bp, "=%02X", ch); - bp += 3; + strbuf_add(sb, line + last, i - last); + strbuf_addf(sb, "=%02X", ch); + last = i + 1; } - else - *bp++ = ch; } - memcpy(bp, "?=", 2); - bp += 2; - return bp - buf; + strbuf_add(sb, line + last, len - last); + strbuf_addstr(sb, "?="); } static unsigned long bound_rfc2047(unsigned long len, const char *encoding) @@ -537,21 +528,21 @@ static unsigned long bound_rfc2047(unsigned long len, const char *encoding) return len * 3 + elen + 100; } -static int add_user_info(const char *what, enum cmit_fmt fmt, char *buf, +static void add_user_info(const char *what, enum cmit_fmt fmt, struct strbuf *sb, const char *line, enum date_mode dmode, const char *encoding) { char *date; int namelen; unsigned long time; - int tz, ret; + int tz; const char *filler = " "; if (fmt == CMIT_FMT_ONELINE) - return 0; + return; date = strchr(line, '>'); if (!date) - return 0; + return; namelen = ++date - line; time = strtoul(date, &date, 10); tz = strtol(date, NULL, 10); @@ -560,42 +551,35 @@ static int add_user_info(const char *what, enum cmit_fmt fmt, char *buf, char *name_tail = strchr(line, '<'); int display_name_length; if (!name_tail) - return 0; + return; while (line < name_tail && isspace(name_tail[-1])) name_tail--; display_name_length = name_tail - line; filler = ""; - strcpy(buf, "From: "); - ret = strlen(buf); - ret += add_rfc2047(buf + ret, line, display_name_length, - encoding); - memcpy(buf + ret, name_tail, namelen - display_name_length); - ret += namelen - display_name_length; - buf[ret++] = '\n'; + strbuf_addstr(sb, "From: "); + add_rfc2047(sb, line, display_name_length, encoding); + strbuf_add(sb, name_tail, namelen - display_name_length); + strbuf_addch(sb, '\n'); } else { - ret = sprintf(buf, "%s: %.*s%.*s\n", what, + strbuf_addf(sb, "%s: %.*s%.*s\n", what, (fmt == CMIT_FMT_FULLER) ? 4 : 0, filler, namelen, line); } switch (fmt) { case CMIT_FMT_MEDIUM: - ret += sprintf(buf + ret, "Date: %s\n", - show_date(time, tz, dmode)); + strbuf_addf(sb, "Date: %s\n", show_date(time, tz, dmode)); break; case CMIT_FMT_EMAIL: - ret += sprintf(buf + ret, "Date: %s\n", - show_date(time, tz, DATE_RFC2822)); + strbuf_addf(sb, "Date: %s\n", show_date(time, tz, DATE_RFC2822)); break; case CMIT_FMT_FULLER: - ret += sprintf(buf + ret, "%sDate: %s\n", what, - show_date(time, tz, dmode)); + strbuf_addf(sb, "%sDate: %s\n", what, show_date(time, tz, dmode)); break; default: /* notin' */ break; } - return ret; } static int is_empty_line(const char *line, int *len_p) @@ -607,16 +591,16 @@ static int is_empty_line(const char *line, int *len_p) return !len; } -static int add_merge_info(enum cmit_fmt fmt, char *buf, const struct commit *commit, int abbrev) +static void add_merge_info(enum cmit_fmt fmt, struct strbuf *sb, + const struct commit *commit, int abbrev) { struct commit_list *parent = commit->parents; - int offset; if ((fmt == CMIT_FMT_ONELINE) || (fmt == CMIT_FMT_EMAIL) || !parent || !parent->next) - return 0; + return; - offset = sprintf(buf, "Merge:"); + strbuf_addstr(sb, "Merge:"); while (parent) { struct commit *p = parent->item; @@ -629,10 +613,9 @@ static int add_merge_info(enum cmit_fmt fmt, char *buf, const struct commit *com dots = (abbrev && strlen(hex) != 40) ? "..." : ""; parent = parent->next; - offset += sprintf(buf + offset, " %s%s", hex, dots); + strbuf_addf(sb, " %s%s", hex, dots); } - buf[offset++] = '\n'; - return offset; + strbuf_addch(sb, '\n'); } static char *get_header(const struct commit *commit, const char *key) @@ -787,8 +770,8 @@ static void fill_person(struct interp *table, const char *msg, int len) interp_set_entry(table, 6, show_date(date, tz, DATE_ISO8601)); } -long format_commit_message(const struct commit *commit, const void *format, - char **buf_p, unsigned long *space_p) +void format_commit_message(const struct commit *commit, + const void *format, struct strbuf *sb) { struct interp table[] = { { "%H" }, /* commit hash */ @@ -841,6 +824,7 @@ long format_commit_message(const struct commit *commit, const void *format, }; struct commit_list *p; char parents[1024]; + unsigned long len; int i; enum { HEADER, SUBJECT, BODY } state; const char *msg = commit->buffer; @@ -921,20 +905,15 @@ long format_commit_message(const struct commit *commit, const void *format, if (!table[i].value) interp_set_entry(table, i, ""); - do { - char *buf = *buf_p; - unsigned long len; - - len = interpolate(buf, *space_p, format, - table, ARRAY_SIZE(table)); - if (len < *space_p) - break; - ALLOC_GROW(buf, len + 1, *space_p); - *buf_p = buf; - } while (1); + len = interpolate(sb->buf + sb->len, strbuf_avail(sb), + format, table, ARRAY_SIZE(table)); + if (len > strbuf_avail(sb)) { + strbuf_grow(sb, len); + interpolate(sb->buf + sb->len, strbuf_avail(sb) + 1, + format, table, ARRAY_SIZE(table)); + } + strbuf_setlen(sb, sb->len + len); interp_clear_table(table, ARRAY_SIZE(table)); - - return strlen(*buf_p); } static void pp_header(enum cmit_fmt fmt, @@ -943,34 +922,24 @@ static void pp_header(enum cmit_fmt fmt, const char *encoding, const struct commit *commit, const char **msg_p, - unsigned long *len_p, - unsigned long *ofs_p, - char **buf_p, - unsigned long *space_p) + struct strbuf *sb) { int parents_shown = 0; for (;;) { const char *line = *msg_p; - char *dst; - int linelen = get_one_line(*msg_p, *len_p); - unsigned long len; + int linelen = get_one_line(*msg_p); if (!linelen) return; *msg_p += linelen; - *len_p -= linelen; if (linelen == 1) /* End of header */ return; - ALLOC_GROW(*buf_p, linelen + *ofs_p + 20, *space_p); - dst = *buf_p + *ofs_p; - if (fmt == CMIT_FMT_RAW) { - memcpy(dst, line, linelen); - *ofs_p += linelen; + strbuf_add(sb, line, linelen); continue; } @@ -988,10 +957,8 @@ static void pp_header(enum cmit_fmt fmt, parent = parent->next, num++) ; /* with enough slop */ - num = *ofs_p + num * 50 + 20; - ALLOC_GROW(*buf_p, num, *space_p); - dst = *buf_p + *ofs_p; - *ofs_p += add_merge_info(fmt, dst, commit, abbrev); + strbuf_grow(sb, num * 50 + 20); + add_merge_info(fmt, sb, commit, abbrev); parents_shown = 1; } @@ -1001,129 +968,99 @@ static void pp_header(enum cmit_fmt fmt, * FULLER shows both authors and dates. */ if (!memcmp(line, "author ", 7)) { - len = linelen; + unsigned long len = linelen; if (fmt == CMIT_FMT_EMAIL) len = bound_rfc2047(linelen, encoding); - ALLOC_GROW(*buf_p, *ofs_p + len + 80, *space_p); - dst = *buf_p + *ofs_p; - *ofs_p += add_user_info("Author", fmt, dst, - line + 7, dmode, encoding); + strbuf_grow(sb, len + 80); + add_user_info("Author", fmt, sb, line + 7, dmode, encoding); } if (!memcmp(line, "committer ", 10) && (fmt == CMIT_FMT_FULL || fmt == CMIT_FMT_FULLER)) { - len = linelen; + unsigned long len = linelen; if (fmt == CMIT_FMT_EMAIL) len = bound_rfc2047(linelen, encoding); - ALLOC_GROW(*buf_p, *ofs_p + len + 80, *space_p); - dst = *buf_p + *ofs_p; - *ofs_p += add_user_info("Commit", fmt, dst, - line + 10, dmode, encoding); + strbuf_grow(sb, len + 80); + add_user_info("Commit", fmt, sb, line + 10, dmode, encoding); } } } static void pp_title_line(enum cmit_fmt fmt, const char **msg_p, - unsigned long *len_p, - unsigned long *ofs_p, - char **buf_p, - unsigned long *space_p, - int indent, + struct strbuf *sb, const char *subject, const char *after_subject, const char *encoding, int plain_non_ascii) { - char *title; - unsigned long title_alloc, title_len; + struct strbuf title; unsigned long len; - title_len = 0; - title_alloc = 80; - title = xmalloc(title_alloc); + strbuf_init(&title, 80); + for (;;) { const char *line = *msg_p; - int linelen = get_one_line(line, *len_p); - *msg_p += linelen; - *len_p -= linelen; + int linelen = get_one_line(line); + *msg_p += linelen; if (!linelen || is_empty_line(line, &linelen)) break; - if (title_alloc <= title_len + linelen + 2) { - title_alloc = title_len + linelen + 80; - title = xrealloc(title, title_alloc); - } - len = 0; - if (title_len) { + strbuf_grow(&title, linelen + 2); + if (title.len) { if (fmt == CMIT_FMT_EMAIL) { - len++; - title[title_len++] = '\n'; + strbuf_addch(&title, '\n'); } - len++; - title[title_len++] = ' '; + strbuf_addch(&title, ' '); } - memcpy(title + title_len, line, linelen); - title_len += linelen; + strbuf_add(&title, line, linelen); } /* Enough slop for the MIME header and rfc2047 */ - len = bound_rfc2047(title_len, encoding)+ 1000; + len = bound_rfc2047(title.len, encoding) + 1000; if (subject) len += strlen(subject); if (after_subject) len += strlen(after_subject); if (encoding) len += strlen(encoding); - ALLOC_GROW(*buf_p, title_len + *ofs_p + len, *space_p); + strbuf_grow(sb, title.len + len); if (subject) { - len = strlen(subject); - memcpy(*buf_p + *ofs_p, subject, len); - *ofs_p += len; - *ofs_p += add_rfc2047(*buf_p + *ofs_p, - title, title_len, encoding); + strbuf_addstr(sb, subject); + add_rfc2047(sb, title.buf, title.len, encoding); } else { - memcpy(*buf_p + *ofs_p, title, title_len); - *ofs_p += title_len; + strbuf_addbuf(sb, &title); } - (*buf_p)[(*ofs_p)++] = '\n'; + strbuf_addch(sb, '\n'); + if (plain_non_ascii) { const char *header_fmt = "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=%s\n" "Content-Transfer-Encoding: 8bit\n"; - *ofs_p += snprintf(*buf_p + *ofs_p, - *space_p - *ofs_p, - header_fmt, encoding); + strbuf_addf(sb, header_fmt, encoding); } if (after_subject) { - len = strlen(after_subject); - memcpy(*buf_p + *ofs_p, after_subject, len); - *ofs_p += len; + strbuf_addstr(sb, after_subject); } - free(title); if (fmt == CMIT_FMT_EMAIL) { - ALLOC_GROW(*buf_p, *ofs_p + 20, *space_p); - (*buf_p)[(*ofs_p)++] = '\n'; + strbuf_addch(sb, '\n'); } + strbuf_release(&title); } static void pp_remainder(enum cmit_fmt fmt, const char **msg_p, - unsigned long *len_p, - unsigned long *ofs_p, - char **buf_p, - unsigned long *space_p, + struct strbuf *sb, int indent) { int first = 1; for (;;) { const char *line = *msg_p; - int linelen = get_one_line(line, *len_p); + int linelen = get_one_line(line); *msg_p += linelen; - *len_p -= linelen; if (!linelen) break; @@ -1136,36 +1073,32 @@ static void pp_remainder(enum cmit_fmt fmt, } first = 0; - ALLOC_GROW(*buf_p, *ofs_p + linelen + indent + 20, *space_p); + strbuf_grow(sb, linelen + indent + 20); if (indent) { - memset(*buf_p + *ofs_p, ' ', indent); - *ofs_p += indent; + memset(sb->buf + sb->len, ' ', indent); + strbuf_setlen(sb, sb->len + indent); } - memcpy(*buf_p + *ofs_p, line, linelen); - *ofs_p += linelen; - (*buf_p)[(*ofs_p)++] = '\n'; + strbuf_add(sb, line, linelen); + strbuf_addch(sb, '\n'); } } -unsigned long pretty_print_commit(enum cmit_fmt fmt, - const struct commit *commit, - unsigned long len, - char **buf_p, unsigned long *space_p, - int abbrev, const char *subject, - const char *after_subject, +void pretty_print_commit(enum cmit_fmt fmt, const struct commit *commit, + struct strbuf *sb, int abbrev, + const char *subject, const char *after_subject, enum date_mode dmode) { - unsigned long offset = 0; unsigned long beginning_of_body; int indent = 4; const char *msg = commit->buffer; int plain_non_ascii = 0; char *reencoded; const char *encoding; - char *buf; - if (fmt == CMIT_FMT_USERFORMAT) - return format_commit_message(commit, user_format, buf_p, space_p); + if (fmt == CMIT_FMT_USERFORMAT) { + format_commit_message(commit, user_format, sb); + return; + } encoding = (git_log_output_encoding ? git_log_output_encoding @@ -1175,7 +1108,6 @@ unsigned long pretty_print_commit(enum cmit_fmt fmt, reencoded = logmsg_reencode(commit, encoding); if (reencoded) { msg = reencoded; - len = strlen(reencoded); } if (fmt == CMIT_FMT_ONELINE || fmt == CMIT_FMT_EMAIL) @@ -1190,14 +1122,13 @@ unsigned long pretty_print_commit(enum cmit_fmt fmt, if (fmt == CMIT_FMT_EMAIL && !after_subject) { int i, ch, in_body; - for (in_body = i = 0; (ch = msg[i]) && i < len; i++) { + for (in_body = i = 0; (ch = msg[i]); i++) { if (!in_body) { /* author could be non 7-bit ASCII but * the log may be so; skip over the * header part first. */ - if (ch == '\n' && - i + 1 < len && msg[i+1] == '\n') + if (ch == '\n' && msg[i+1] == '\n') in_body = 1; } else if (non_ascii(ch)) { @@ -1207,59 +1138,44 @@ unsigned long pretty_print_commit(enum cmit_fmt fmt, } } - pp_header(fmt, abbrev, dmode, encoding, - commit, &msg, &len, - &offset, buf_p, space_p); + pp_header(fmt, abbrev, dmode, encoding, commit, &msg, sb); if (fmt != CMIT_FMT_ONELINE && !subject) { - ALLOC_GROW(*buf_p, offset + 20, *space_p); - (*buf_p)[offset++] = '\n'; + strbuf_addch(sb, '\n'); } /* Skip excess blank lines at the beginning of body, if any... */ for (;;) { - int linelen = get_one_line(msg, len); + int linelen = get_one_line(msg); int ll = linelen; if (!linelen) break; if (!is_empty_line(msg, &ll)) break; msg += linelen; - len -= linelen; } /* These formats treat the title line specially. */ - if (fmt == CMIT_FMT_ONELINE - || fmt == CMIT_FMT_EMAIL) - pp_title_line(fmt, &msg, &len, &offset, - buf_p, space_p, indent, - subject, after_subject, encoding, - plain_non_ascii); - - beginning_of_body = offset; - if (fmt != CMIT_FMT_ONELINE) - pp_remainder(fmt, &msg, &len, &offset, - buf_p, space_p, indent); - - while (offset && isspace((*buf_p)[offset-1])) - offset--; + if (fmt == CMIT_FMT_ONELINE || fmt == CMIT_FMT_EMAIL) + pp_title_line(fmt, &msg, sb, subject, + after_subject, encoding, plain_non_ascii); - ALLOC_GROW(*buf_p, offset + 20, *space_p); - buf = *buf_p; + beginning_of_body = sb->len; + if (fmt != CMIT_FMT_ONELINE) + pp_remainder(fmt, &msg, sb, indent); + strbuf_rtrim(sb); /* Make sure there is an EOLN for the non-oneline case */ if (fmt != CMIT_FMT_ONELINE) - buf[offset++] = '\n'; + strbuf_addch(sb, '\n'); /* * The caller may append additional body text in e-mail * format. Make sure we did not strip the blank line * between the header and the body. */ - if (fmt == CMIT_FMT_EMAIL && offset <= beginning_of_body) - buf[offset++] = '\n'; - buf[offset] = '\0'; + if (fmt == CMIT_FMT_EMAIL && sb->len <= beginning_of_body) + strbuf_addch(sb, '\n'); free(reencoded); - return offset; } struct commit *pop_commit(struct commit_list **stack) @@ -1338,12 +1254,12 @@ void sort_in_topological_order_fn(struct commit_list ** list, int lifo, next=next->next; } /* - * find the tips - * - * tips are nodes not reachable from any other node in the list - * - * the tips serve as a starting set for the work queue. - */ + * find the tips + * + * tips are nodes not reachable from any other node in the list + * + * the tips serve as a starting set for the work queue. + */ next=*list; insert = &work; while (next) { @@ -1370,9 +1286,9 @@ void sort_in_topological_order_fn(struct commit_list ** list, int lifo, if (pn) { /* * parents are only enqueued for emission - * when all their children have been emitted thereby - * guaranteeing topological order. - */ + * when all their children have been emitted thereby + * guaranteeing topological order. + */ pn->indegree--; if (!pn->indegree) { if (!lifo) @@ -1384,9 +1300,9 @@ void sort_in_topological_order_fn(struct commit_list ** list, int lifo, parents=parents->next; } /* - * work_item is a commit all of whose children - * have already been emitted. we can emit it now. - */ + * work_item is a commit all of whose children + * have already been emitted. we can emit it now. + */ *pptr = work_node->list_item; pptr = &(*pptr)->next; *pptr = NULL; @@ -1482,8 +1398,7 @@ static struct commit_list *merge_bases(struct commit *one, struct commit *two) } struct commit_list *get_merge_bases(struct commit *one, - struct commit *two, - int cleanup) + struct commit *two, int cleanup) { struct commit_list *list; struct commit **rslt; diff --git a/commit.h b/commit.h index a8d76616d2..b779de8cbc 100644 --- a/commit.h +++ b/commit.h @@ -3,6 +3,7 @@ #include "object.h" #include "tree.h" +#include "strbuf.h" #include "decorate.h" struct commit_list { @@ -61,8 +62,12 @@ enum cmit_fmt { }; extern enum cmit_fmt get_commit_format(const char *arg); -extern long format_commit_message(const struct commit *commit, const void *template, char **buf_p, unsigned long *space_p); -extern unsigned long pretty_print_commit(enum cmit_fmt fmt, const struct commit *, unsigned long len, char **buf_p, unsigned long *space_p, int abbrev, const char *subject, const char *after_subject, enum date_mode dmode); +extern void format_commit_message(const struct commit *commit, + const void *format, struct strbuf *sb); +extern void pretty_print_commit(enum cmit_fmt fmt, const struct commit*, + struct strbuf *, + int abbrev, const char *subject, + const char *after_subject, enum date_mode); /** Removes the first commit from a list sorted by date, and adds all * of its parents. diff --git a/log-tree.c b/log-tree.c index a6423718e7..3e5e6acfaf 100644 --- a/log-tree.c +++ b/log-tree.c @@ -79,25 +79,14 @@ static int detect_any_signoff(char *letter, int size) return seen_head && seen_name; } -static unsigned long append_signoff(char **buf_p, unsigned long *buf_sz_p, - unsigned long at, const char *signoff) +static void append_signoff(struct strbuf *sb, const char *signoff) { static const char signed_off_by[] = "Signed-off-by: "; size_t signoff_len = strlen(signoff); int has_signoff = 0; char *cp; - char *buf; - unsigned long buf_sz; - - buf = *buf_p; - buf_sz = *buf_sz_p; - if (buf_sz <= at + strlen(signed_off_by) + signoff_len + 3) { - buf_sz += strlen(signed_off_by) + signoff_len + 3; - buf = xrealloc(buf, buf_sz); - *buf_p = buf; - *buf_sz_p = buf_sz; - } - cp = buf; + + cp = sb->buf; /* First see if we already have the sign-off by the signer */ while ((cp = strstr(cp, signed_off_by))) { @@ -105,29 +94,25 @@ static unsigned long append_signoff(char **buf_p, unsigned long *buf_sz_p, has_signoff = 1; cp += strlen(signed_off_by); - if (cp + signoff_len >= buf + at) + if (cp + signoff_len >= sb->buf + sb->len) break; if (strncmp(cp, signoff, signoff_len)) continue; if (!isspace(cp[signoff_len])) continue; /* we already have him */ - return at; + return; } if (!has_signoff) - has_signoff = detect_any_signoff(buf, at); + has_signoff = detect_any_signoff(sb->buf, sb->len); if (!has_signoff) - buf[at++] = '\n'; - - strcpy(buf + at, signed_off_by); - at += strlen(signed_off_by); - strcpy(buf + at, signoff); - at += signoff_len; - buf[at++] = '\n'; - buf[at] = 0; - return at; + strbuf_addch(sb, '\n'); + + strbuf_addstr(sb, signed_off_by); + strbuf_add(sb, signoff, signoff_len); + strbuf_addch(sb, '\n'); } static unsigned int digits_in_number(unsigned int number) @@ -142,14 +127,12 @@ static unsigned int digits_in_number(unsigned int number) void show_log(struct rev_info *opt, const char *sep) { - char *msgbuf = NULL; - unsigned long msgbuf_len = 0; + struct strbuf msgbuf; struct log_info *log = opt->loginfo; struct commit *commit = log->commit, *parent = log->parent; int abbrev = opt->diffopt.abbrev; int abbrev_commit = opt->abbrev_commit ? opt->abbrev : 40; const char *extra; - int len; const char *subject = NULL, *extra_headers = opt->extra_headers; opt->loginfo = NULL; @@ -288,18 +271,17 @@ void show_log(struct rev_info *opt, const char *sep) /* * And then the pretty-printed message itself */ - len = pretty_print_commit(opt->commit_format, commit, ~0u, - &msgbuf, &msgbuf_len, abbrev, subject, - extra_headers, opt->date_mode); + strbuf_init(&msgbuf, 0); + pretty_print_commit(opt->commit_format, commit, &msgbuf, + abbrev, subject, extra_headers, opt->date_mode); if (opt->add_signoff) - len = append_signoff(&msgbuf, &msgbuf_len, len, - opt->add_signoff); + append_signoff(&msgbuf, opt->add_signoff); if (opt->show_log_size) - printf("log size %i\n", len); + printf("log size %i\n", (int)msgbuf.len); - printf("%s%s%s", msgbuf, extra, sep); - free(msgbuf); + printf("%s%s%s", msgbuf.buf, extra, sep); + strbuf_release(&msgbuf); } int log_tree_diff_flush(struct rev_info *opt) -- cgit v1.2.3 From a08f23ab3eab67aac7163a284038f45fa99ef66f Mon Sep 17 00:00:00 2001 From: Pierre Habouzit Date: Sat, 15 Sep 2007 23:50:12 +0200 Subject: Refactor replace_encoding_header. * Be more clever in how we search for "encoding ...\n": parse for real instead of the sloppy strstr's. * use strbuf_splice to do the substring replacements. Signed-off-by: Pierre Habouzit Acked-by: Linus Torvalds Signed-off-by: Junio C Hamano --- commit.c | 59 +++++++++++++++++++++++------------------------------------ 1 file changed, 23 insertions(+), 36 deletions(-) (limited to 'commit.c') diff --git a/commit.c b/commit.c index 6602e2c72f..13af93363e 100644 --- a/commit.c +++ b/commit.c @@ -648,47 +648,34 @@ static char *get_header(const struct commit *commit, const char *key) static char *replace_encoding_header(char *buf, const char *encoding) { - char *encoding_header = strstr(buf, "\nencoding "); - char *header_end = strstr(buf, "\n\n"); - char *end_of_encoding_header; - int encoding_header_pos; - int encoding_header_len; - int new_len; - int need_len; - int buflen = strlen(buf) + 1; - - if (!header_end) - header_end = buf + buflen; - if (!encoding_header || encoding_header >= header_end) - return buf; - encoding_header++; - end_of_encoding_header = strchr(encoding_header, '\n'); - if (!end_of_encoding_header) + struct strbuf tmp; + size_t start, len; + char *cp = buf; + + /* guess if there is an encoding header before a \n\n */ + while (strncmp(cp, "encoding ", strlen("encoding "))) { + cp = strchr(cp, '\n'); + if (!cp || *++cp == '\n') + return buf; + } + start = cp - buf; + cp = strchr(cp, '\n'); + if (!cp) return buf; /* should not happen but be defensive */ - end_of_encoding_header++; - - encoding_header_len = end_of_encoding_header - encoding_header; - encoding_header_pos = encoding_header - buf; + len = cp + 1 - (buf + start); + strbuf_init(&tmp, 0); + strbuf_attach(&tmp, buf, strlen(buf), strlen(buf) + 1); if (is_encoding_utf8(encoding)) { /* we have re-coded to UTF-8; drop the header */ - memmove(encoding_header, end_of_encoding_header, - buflen - (encoding_header_pos + encoding_header_len)); - return buf; - } - new_len = strlen(encoding); - need_len = new_len + strlen("encoding \n"); - if (encoding_header_len < need_len) { - buf = xrealloc(buf, buflen + (need_len - encoding_header_len)); - encoding_header = buf + encoding_header_pos; - end_of_encoding_header = encoding_header + encoding_header_len; + strbuf_splice(&tmp, start, len, NULL, 0); + } else { + /* just replaces XXXX in 'encoding XXXX\n' */ + strbuf_splice(&tmp, start + strlen("encoding "), + len - strlen("encoding \n"), + encoding, strlen(encoding)); } - memmove(end_of_encoding_header + (need_len - encoding_header_len), - end_of_encoding_header, - buflen - (encoding_header_pos + encoding_header_len)); - memcpy(encoding_header + 9, encoding, strlen(encoding)); - encoding_header[9 + new_len] = '\n'; - return buf; + return tmp.buf; } static char *logmsg_reencode(const struct commit *commit, -- cgit v1.2.3 From 8b6087fb25068d6af927f112a93dc056930f3108 Mon Sep 17 00:00:00 2001 From: Pierre Habouzit Date: Sun, 16 Sep 2007 10:19:01 +0200 Subject: Remove preemptive allocations. Careful profiling shows that we spend more time guessing what pattern allocation will have, whereas we can delay it only at the point where add_rfc2047 will be used and don't allocate huge memory area for the many cases where it's not. Signed-off-by: Pierre Habouzit Acked-by: Linus Torvalds Signed-off-by: Junio C Hamano --- commit.c | 35 +++++------------------------------ 1 file changed, 5 insertions(+), 30 deletions(-) (limited to 'commit.c') diff --git a/commit.c b/commit.c index 13af93363e..85889f9664 100644 --- a/commit.c +++ b/commit.c @@ -501,6 +501,7 @@ static void add_rfc2047(struct strbuf *sb, const char *line, int len, return; needquote: + strbuf_grow(sb, len * 3 + strlen(encoding) + 100); strbuf_addf(sb, "=?%s?q?", encoding); for (i = last = 0; i < len; i++) { unsigned ch = line[i] & 0xFF; @@ -520,14 +521,6 @@ needquote: strbuf_addstr(sb, "?="); } -static unsigned long bound_rfc2047(unsigned long len, const char *encoding) -{ - /* upper bound of q encoded string of length 'len' */ - unsigned long elen = strlen(encoding); - - return len * 3 + elen + 100; -} - static void add_user_info(const char *what, enum cmit_fmt fmt, struct strbuf *sb, const char *line, enum date_mode dmode, const char *encoding) @@ -560,8 +553,7 @@ static void add_user_info(const char *what, enum cmit_fmt fmt, struct strbuf *sb add_rfc2047(sb, line, display_name_length, encoding); strbuf_add(sb, name_tail, namelen - display_name_length); strbuf_addch(sb, '\n'); - } - else { + } else { strbuf_addf(sb, "%s: %.*s%.*s\n", what, (fmt == CMIT_FMT_FULLER) ? 4 : 0, filler, namelen, line); @@ -955,19 +947,12 @@ static void pp_header(enum cmit_fmt fmt, * FULLER shows both authors and dates. */ if (!memcmp(line, "author ", 7)) { - unsigned long len = linelen; - if (fmt == CMIT_FMT_EMAIL) - len = bound_rfc2047(linelen, encoding); - strbuf_grow(sb, len + 80); + strbuf_grow(sb, linelen + 80); add_user_info("Author", fmt, sb, line + 7, dmode, encoding); } - if (!memcmp(line, "committer ", 10) && (fmt == CMIT_FMT_FULL || fmt == CMIT_FMT_FULLER)) { - unsigned long len = linelen; - if (fmt == CMIT_FMT_EMAIL) - len = bound_rfc2047(linelen, encoding); - strbuf_grow(sb, len + 80); + strbuf_grow(sb, linelen + 80); add_user_info("Commit", fmt, sb, line + 10, dmode, encoding); } } @@ -982,7 +967,6 @@ static void pp_title_line(enum cmit_fmt fmt, int plain_non_ascii) { struct strbuf title; - unsigned long len; strbuf_init(&title, 80); @@ -1004,16 +988,7 @@ static void pp_title_line(enum cmit_fmt fmt, strbuf_add(&title, line, linelen); } - /* Enough slop for the MIME header and rfc2047 */ - len = bound_rfc2047(title.len, encoding) + 1000; - if (subject) - len += strlen(subject); - if (after_subject) - len += strlen(after_subject); - if (encoding) - len += strlen(encoding); - - strbuf_grow(sb, title.len + len); + strbuf_grow(sb, title.len + 1024); if (subject) { strbuf_addstr(sb, subject); add_rfc2047(sb, title.buf, title.len, encoding); -- cgit v1.2.3 From 182af8343c307436bb5364309aa6d4d46fa5911d Mon Sep 17 00:00:00 2001 From: Pierre Habouzit Date: Sun, 16 Sep 2007 00:32:36 +0200 Subject: Use xmemdupz() in many places. Signed-off-by: Pierre Habouzit Signed-off-by: Junio C Hamano --- attr.c | 7 +------ builtin-add.c | 8 ++------ builtin-apply.c | 11 ++--------- builtin-fetch--tool.c | 6 +----- builtin-fmt-merge-msg.c | 17 ++++++----------- builtin-for-each-ref.c | 40 +++++++++------------------------------- builtin-log.c | 12 ++---------- builtin-ls-files.c | 9 +-------- builtin-mv.c | 5 +---- builtin-revert.c | 4 +--- builtin-shortlog.c | 11 ++--------- commit.c | 16 ++++++---------- connect.c | 4 +--- convert.c | 7 +------ diff.c | 13 ++----------- diffcore-order.c | 7 ++----- fast-import.c | 4 +--- http-push.c | 9 ++------- imap-send.c | 20 +++++--------------- merge-recursive.c | 19 ++++--------------- refs.c | 12 ++++-------- sha1_file.c | 12 +++--------- tag.c | 4 +--- 23 files changed, 60 insertions(+), 197 deletions(-) (limited to 'commit.c') diff --git a/attr.c b/attr.c index 129399310a..92704a3f61 100644 --- a/attr.c +++ b/attr.c @@ -160,12 +160,7 @@ static const char *parse_attr(const char *src, int lineno, const char *cp, else if (!equals) e->setto = ATTR__TRUE; else { - char *value; - int vallen = ep - equals; - value = xmalloc(vallen); - memcpy(value, equals+1, vallen-1); - value[vallen-1] = 0; - e->setto = value; + e->setto = xmemdupz(equals + 1, ep - equals - 1); } e->attr = git_attr(cp, len); } diff --git a/builtin-add.c b/builtin-add.c index 0d7d0ce420..f9a65803d8 100644 --- a/builtin-add.c +++ b/builtin-add.c @@ -71,12 +71,8 @@ static void fill_directory(struct dir_struct *dir, const char **pathspec, baselen = common_prefix(pathspec); path = "."; base = ""; - if (baselen) { - char *common = xmalloc(baselen + 1); - memcpy(common, *pathspec, baselen); - common[baselen] = 0; - path = base = common; - } + if (baselen) + path = base = xmemdupz(*pathspec, baselen); /* Read the directory and prune it */ read_directory(dir, path, base, baselen, pathspec); diff --git a/builtin-apply.c b/builtin-apply.c index f953c5b768..512c9b6142 100644 --- a/builtin-apply.c +++ b/builtin-apply.c @@ -293,11 +293,7 @@ static char *find_name(const char *line, char *def, int p_value, int terminate) return def; } - name = xmalloc(len + 1); - memcpy(name, start, len); - name[len] = 0; - free(def); - return name; + return xmemdupz(start, len); } static int count_slashes(const char *cp) @@ -687,10 +683,7 @@ static char *git_header_name(char *line, int llen) break; } if (second[len] == '\n' && !memcmp(name, second, len)) { - char *ret = xmalloc(len + 1); - memcpy(ret, name, len); - ret[len] = 0; - return ret; + return xmemdupz(name, len); } } } diff --git a/builtin-fetch--tool.c b/builtin-fetch--tool.c index 514a3cc018..349b59c258 100644 --- a/builtin-fetch--tool.c +++ b/builtin-fetch--tool.c @@ -222,19 +222,15 @@ static char *find_local_name(const char *remote_name, const char *refs, } if (!strncmp(remote_name, ref, len) && ref[len] == ':') { const char *local_part = ref + len + 1; - char *ret; int retlen; if (!next) retlen = strlen(local_part); else retlen = next - local_part; - ret = xmalloc(retlen + 1); - memcpy(ret, local_part, retlen); - ret[retlen] = 0; *force_p = single_force; *not_for_merge_p = not_for_merge; - return ret; + return xmemdupz(local_part, retlen); } ref = next; } diff --git a/builtin-fmt-merge-msg.c b/builtin-fmt-merge-msg.c index ae60fccea7..8a3c962f89 100644 --- a/builtin-fmt-merge-msg.c +++ b/builtin-fmt-merge-msg.c @@ -140,12 +140,10 @@ static int handle_line(char *line) if (!strcmp(".", src) || !strcmp(src, origin)) { int len = strlen(origin); if (origin[0] == '\'' && origin[len - 1] == '\'') { - char *new_origin = xmalloc(len - 1); - memcpy(new_origin, origin + 1, len - 2); - new_origin[len - 2] = 0; - origin = new_origin; - } else + origin = xmemdupz(origin + 1, len - 2); + } else { origin = xstrdup(origin); + } } else { char *new_origin = xmalloc(strlen(origin) + strlen(src) + 5); sprintf(new_origin, "%s of %s", origin, src); @@ -211,14 +209,11 @@ static void shortlog(const char *name, unsigned char *sha1, bol += 2; eol = strchr(bol, '\n'); - if (eol) { - int len = eol - bol; - oneline = xmalloc(len + 1); - memcpy(oneline, bol, len); - oneline[len] = 0; - } else + oneline = xmemdupz(bol, eol - bol); + } else { oneline = xstrdup(bol); + } append_to_list(&subjects, oneline, NULL); } diff --git a/builtin-for-each-ref.c b/builtin-for-each-ref.c index 0afa1c5c41..725c1df0fc 100644 --- a/builtin-for-each-ref.c +++ b/builtin-for-each-ref.c @@ -87,7 +87,6 @@ static int used_atom_cnt, sort_atom_limit, need_tagged; static int parse_atom(const char *atom, const char *ep) { const char *sp; - char *n; int i, at; sp = atom; @@ -120,10 +119,7 @@ static int parse_atom(const char *atom, const char *ep) (sizeof *used_atom) * used_atom_cnt); used_atom_type = xrealloc(used_atom_type, (sizeof(*used_atom_type) * used_atom_cnt)); - n = xmalloc(ep - atom + 1); - memcpy(n, atom, ep - atom); - n[ep-atom] = 0; - used_atom[at] = n; + used_atom[at] = xmemdupz(atom, ep - atom); used_atom_type[at] = valid_atom[i].cmp_type; return at; } @@ -305,46 +301,28 @@ static const char *find_wholine(const char *who, int wholen, const char *buf, un static const char *copy_line(const char *buf) { const char *eol = strchr(buf, '\n'); - char *line; - int len; if (!eol) return ""; - len = eol - buf; - line = xmalloc(len + 1); - memcpy(line, buf, len); - line[len] = 0; - return line; + return xmemdupz(buf, eol - buf); } static const char *copy_name(const char *buf) { - const char *eol = strchr(buf, '\n'); - const char *eoname = strstr(buf, " <"); - char *line; - int len; - if (!(eoname && eol && eoname < eol)) - return ""; - len = eoname - buf; - line = xmalloc(len + 1); - memcpy(line, buf, len); - line[len] = 0; - return line; + const char *cp; + for (cp = buf; *cp != '\n'; cp++) { + if (!strncmp(cp, " <", 2)) + return xmemdupz(buf, cp - buf); + } + return ""; } static const char *copy_email(const char *buf) { const char *email = strchr(buf, '<'); const char *eoemail = strchr(email, '>'); - char *line; - int len; if (!email || !eoemail) return ""; - eoemail++; - len = eoemail - email; - line = xmalloc(len + 1); - memcpy(line, email, len); - line[len] = 0; - return line; + return xmemdupz(email, eoemail + 1 - email); } static void grab_date(const char *buf, struct atom_value *v) diff --git a/builtin-log.c b/builtin-log.c index 60819d15c5..e8b982db7c 100644 --- a/builtin-log.c +++ b/builtin-log.c @@ -441,8 +441,6 @@ static const char *clean_message_id(const char *msg_id) { char ch; const char *a, *z, *m; - char *n; - size_t len; m = msg_id; while ((ch = *m) && (isspace(ch) || (ch == '<'))) @@ -458,11 +456,7 @@ static const char *clean_message_id(const char *msg_id) die("insane in-reply-to: %s", msg_id); if (++z == m) return a; - len = z - a; - n = xmalloc(len + 1); - memcpy(n, a, len); - n[len] = 0; - return n; + return xmemdupz(a, z - a); } int cmd_format_patch(int argc, const char **argv, const char *prefix) @@ -541,9 +535,7 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) endpos = strchr(committer, '>'); if (!endpos) die("bogos committer info %s\n", committer); - add_signoff = xmalloc(endpos - committer + 2); - memcpy(add_signoff, committer, endpos - committer + 1); - add_signoff[endpos - committer + 1] = 0; + add_signoff = xmemdupz(committer, endpos - committer + 1); } else if (!strcmp(argv[i], "--attach")) { rev.mime_boundary = git_version_string; diff --git a/builtin-ls-files.c b/builtin-ls-files.c index 6c1db86e80..48dd3f77a4 100644 --- a/builtin-ls-files.c +++ b/builtin-ls-files.c @@ -299,7 +299,6 @@ static void prune_cache(const char *prefix) static const char *verify_pathspec(const char *prefix) { const char **p, *n, *prev; - char *real_prefix; unsigned long max; prev = NULL; @@ -326,14 +325,8 @@ static const char *verify_pathspec(const char *prefix) if (prefix_offset > max || memcmp(prev, prefix, prefix_offset)) die("git-ls-files: cannot generate relative filenames containing '..'"); - real_prefix = NULL; prefix_len = max; - if (max) { - real_prefix = xmalloc(max + 1); - memcpy(real_prefix, prev, max); - real_prefix[max] = 0; - } - return real_prefix; + return max ? xmemdupz(prev, max) : NULL; } /* diff --git a/builtin-mv.c b/builtin-mv.c index b95b7d286a..b944651691 100644 --- a/builtin-mv.c +++ b/builtin-mv.c @@ -22,10 +22,7 @@ static const char **copy_pathspec(const char *prefix, const char **pathspec, for (i = 0; i < count; i++) { int length = strlen(result[i]); if (length > 0 && result[i][length - 1] == '/') { - char *without_slash = xmalloc(length); - memcpy(without_slash, result[i], length - 1); - without_slash[length - 1] = '\0'; - result[i] = without_slash; + result[i] = xmemdupz(result[i], length - 1); } if (base_name) { const char *last_slash = strrchr(result[i], '/'); diff --git a/builtin-revert.c b/builtin-revert.c index 499bbe7343..a655c8ee2a 100644 --- a/builtin-revert.c +++ b/builtin-revert.c @@ -168,9 +168,7 @@ static void set_author_ident_env(const char *message) char *line, *pend, *email, *timestamp; p += 7; - line = xmalloc(eol + 1 - p); - memcpy(line, p, eol - p); - line[eol - p] = '\0'; + line = xmemdupz(p, eol - p); email = strchr(line, '<'); if (!email) die ("Could not extract author email from %s", diff --git a/builtin-shortlog.c b/builtin-shortlog.c index 16af6199ab..3fe754677d 100644 --- a/builtin-shortlog.c +++ b/builtin-shortlog.c @@ -39,10 +39,7 @@ static void insert_author_oneline(struct path_list *list, while (authorlen > 0 && isspace(author[authorlen - 1])) authorlen--; - buffer = xmalloc(authorlen + 1); - memcpy(buffer, author, authorlen); - buffer[authorlen] = '\0'; - + buffer = xmemdupz(author, authorlen); item = path_list_insert(buffer, list); if (item->util == NULL) item->util = xcalloc(1, sizeof(struct path_list)); @@ -66,13 +63,9 @@ static void insert_author_oneline(struct path_list *list, oneline++; onelinelen--; } - while (onelinelen > 0 && isspace(oneline[onelinelen - 1])) onelinelen--; - - buffer = xmalloc(onelinelen + 1); - memcpy(buffer, oneline, onelinelen); - buffer[onelinelen] = '\0'; + buffer = xmemdupz(oneline, onelinelen); if (dot3) { int dot3len = strlen(dot3); diff --git a/commit.c b/commit.c index 85889f9664..f86fa776c0 100644 --- a/commit.c +++ b/commit.c @@ -628,11 +628,7 @@ static char *get_header(const struct commit *commit, const char *key) if (eol - line > key_len && !strncmp(line, key, key_len) && line[key_len] == ' ') { - int len = eol - line - key_len; - char *ret = xmalloc(len); - memcpy(ret, line + key_len + 1, len - 1); - ret[len - 1] = '\0'; - return ret; + return xmemdupz(line + key_len + 1, eol - line - key_len - 1); } line = next; } @@ -709,7 +705,7 @@ static void fill_person(struct interp *table, const char *msg, int len) start = end + 1; while (end > 0 && isspace(msg[end - 1])) end--; - table[0].value = xstrndup(msg, end); + table[0].value = xmemdupz(msg, end); if (start >= len) return; @@ -721,7 +717,7 @@ static void fill_person(struct interp *table, const char *msg, int len) if (end >= len) return; - table[1].value = xstrndup(msg + start, end - start); + table[1].value = xmemdupz(msg + start, end - start); /* parse date */ for (start = end + 1; start < len && isspace(msg[start]); start++) @@ -732,7 +728,7 @@ static void fill_person(struct interp *table, const char *msg, int len) if (msg + start == ep) return; - table[5].value = xstrndup(msg + start, ep - (msg + start)); + table[5].value = xmemdupz(msg + start, ep - (msg + start)); /* parse tz */ for (start = ep - msg + 1; start < len && isspace(msg[start]); start++) @@ -859,7 +855,7 @@ void format_commit_message(const struct commit *commit, ; /* do nothing */ if (state == SUBJECT) { - table[ISUBJECT].value = xstrndup(msg + i, eol - i); + table[ISUBJECT].value = xmemdupz(msg + i, eol - i); i = eol; } if (i == eol) { @@ -875,7 +871,7 @@ void format_commit_message(const struct commit *commit, msg + i + 10, eol - i - 10); else if (!prefixcmp(msg + i, "encoding ")) table[IENCODING].value = - xstrndup(msg + i + 9, eol - i - 9); + xmemdupz(msg + i + 9, eol - i - 9); i = eol; } if (msg[i]) diff --git a/connect.c b/connect.c index 8b1e9935a8..1653a0ef7f 100644 --- a/connect.c +++ b/connect.c @@ -393,9 +393,7 @@ static int git_proxy_command_options(const char *var, const char *value) if (matchlen == 4 && !memcmp(value, "none", 4)) matchlen = 0; - git_proxy_command = xmalloc(matchlen + 1); - memcpy(git_proxy_command, value, matchlen); - git_proxy_command[matchlen] = 0; + git_proxy_command = xmemdupz(value, matchlen); } return 0; } diff --git a/convert.c b/convert.c index 508d30b2f1..79c9df2e91 100644 --- a/convert.c +++ b/convert.c @@ -323,13 +323,8 @@ static int read_convert_config(const char *var, const char *value) if (!strncmp(drv->name, name, namelen) && !drv->name[namelen]) break; if (!drv) { - char *namebuf; drv = xcalloc(1, sizeof(struct convert_driver)); - namebuf = xmalloc(namelen + 1); - memcpy(namebuf, name, namelen); - namebuf[namelen] = 0; - drv->name = namebuf; - drv->next = NULL; + drv->name = xmemdupz(name, namelen); *user_convert_tail = drv; user_convert_tail = &(drv->next); } diff --git a/diff.c b/diff.c index a5b69ed2d2..2216d756d1 100644 --- a/diff.c +++ b/diff.c @@ -83,13 +83,8 @@ static int parse_lldiff_command(const char *var, const char *ep, const char *val if (!strncmp(drv->name, name, namelen) && !drv->name[namelen]) break; if (!drv) { - char *namebuf; drv = xcalloc(1, sizeof(struct ll_diff_driver)); - namebuf = xmalloc(namelen + 1); - memcpy(namebuf, name, namelen); - namebuf[namelen] = 0; - drv->name = namebuf; - drv->next = NULL; + drv->name = xmemdupz(name, namelen); if (!user_diff_tail) user_diff_tail = &user_diff; *user_diff_tail = drv; @@ -126,12 +121,8 @@ static int parse_funcname_pattern(const char *var, const char *ep, const char *v if (!strncmp(pp->name, name, namelen) && !pp->name[namelen]) break; if (!pp) { - char *namebuf; pp = xcalloc(1, sizeof(*pp)); - namebuf = xmalloc(namelen + 1); - memcpy(namebuf, name, namelen); - namebuf[namelen] = 0; - pp->name = namebuf; + pp->name = xmemdupz(name, namelen); pp->next = funcname_pattern_list; funcname_pattern_list = pp; } diff --git a/diffcore-order.c b/diffcore-order.c index 2a4bd8232e..23e93852d8 100644 --- a/diffcore-order.c +++ b/diffcore-order.c @@ -48,11 +48,8 @@ static void prepare_order(const char *orderfile) if (*ep == '\n') { *ep = 0; order[cnt] = cp; - } - else { - order[cnt] = xmalloc(ep-cp+1); - memcpy(order[cnt], cp, ep-cp); - order[cnt][ep-cp] = 0; + } else { + order[cnt] = xmemdupz(cp, ep - cp); } cnt++; } diff --git a/fast-import.c b/fast-import.c index e2a4834706..f9906586ee 100644 --- a/fast-import.c +++ b/fast-import.c @@ -1864,9 +1864,7 @@ static void file_change_cr(struct branch *b, int rename) endp = strchr(s, ' '); if (!endp) die("Missing space after source: %s", command_buf.buf); - s_uq = xmalloc(endp - s + 1); - memcpy(s_uq, s, endp - s); - s_uq[endp - s] = 0; + s_uq = xmemdupz(s, endp - s); } s = s_uq; diff --git a/http-push.c b/http-push.c index 7c3720f602..276e1eb1d9 100644 --- a/http-push.c +++ b/http-push.c @@ -1271,10 +1271,7 @@ xml_cdata(void *userData, const XML_Char *s, int len) { struct xml_ctx *ctx = (struct xml_ctx *)userData; free(ctx->cdata); - ctx->cdata = xmalloc(len + 1); - /* NB: 's' is not null-terminated, can not use strlcpy here */ - memcpy(ctx->cdata, s, len); - ctx->cdata[len] = '\0'; + ctx->cdata = xmemdupz(s, len); } static struct remote_lock *lock_remote(const char *path, long timeout) @@ -2172,9 +2169,7 @@ static void fetch_symref(const char *path, char **symref, unsigned char *sha1) /* If it's a symref, set the refname; otherwise try for a sha1 */ if (!prefixcmp((char *)buffer.buffer, "ref: ")) { - *symref = xmalloc(buffer.posn - 5); - memcpy(*symref, (char *)buffer.buffer + 5, buffer.posn - 6); - (*symref)[buffer.posn - 6] = '\0'; + *symref = xmemdupz((char *)buffer.buffer + 5, buffer.posn - 6); } else { get_sha1_hex(buffer.buffer, sha1); } diff --git a/imap-send.c b/imap-send.c index 86e4a0f6a0..905d09746a 100644 --- a/imap-send.c +++ b/imap-send.c @@ -623,9 +623,7 @@ parse_imap_list_l( imap_t *imap, char **sp, list_t **curp, int level ) goto bail; cur->len = s - p; s++; - cur->val = xmalloc( cur->len + 1 ); - memcpy( cur->val, p, cur->len ); - cur->val[cur->len] = 0; + cur->val = xmemdupz(p, cur->len); } else { /* atom */ p = s; @@ -633,12 +631,10 @@ parse_imap_list_l( imap_t *imap, char **sp, list_t **curp, int level ) if (level && *s == ')') break; cur->len = s - p; - if (cur->len == 3 && !memcmp ("NIL", p, 3)) + if (cur->len == 3 && !memcmp ("NIL", p, 3)) { cur->val = NIL; - else { - cur->val = xmalloc( cur->len + 1 ); - memcpy( cur->val, p, cur->len ); - cur->val[cur->len] = 0; + } else { + cur->val = xmemdupz(p, cur->len); } } @@ -1221,13 +1217,7 @@ split_msg( msg_data_t *all_msgs, msg_data_t *msg, int *ofs ) if (p) msg->len = &p[1] - data; - msg->data = xmalloc( msg->len + 1 ); - if (!msg->data) - return 0; - - memcpy( msg->data, data, msg->len ); - msg->data[ msg->len ] = 0; - + msg->data = xmemdupz(data, msg->len); *ofs += msg->len; return 1; } diff --git a/merge-recursive.c b/merge-recursive.c index 19d5f3b287..14b56c2f20 100644 --- a/merge-recursive.c +++ b/merge-recursive.c @@ -432,19 +432,15 @@ static int update_stages(const char *path, struct diff_filespec *o, static int remove_path(const char *name) { - int ret, len; + int ret; char *slash, *dirs; ret = unlink(name); if (ret) return ret; - len = strlen(name); - dirs = xmalloc(len+1); - memcpy(dirs, name, len); - dirs[len] = '\0'; + dirs = xstrdup(name); while ((slash = strrchr(name, '/'))) { *slash = '\0'; - len = slash - name; if (rmdir(name) != 0) break; } @@ -578,9 +574,7 @@ static void update_file_flags(const unsigned char *sha, flush_buffer(fd, buf, size); close(fd); } else if (S_ISLNK(mode)) { - char *lnk = xmalloc(size + 1); - memcpy(lnk, buf, size); - lnk[size] = '\0'; + char *lnk = xmemdupz(buf, size); mkdir_p(path, 0777); unlink(path); symlink(lnk, path); @@ -872,14 +866,9 @@ static int read_merge_config(const char *var, const char *value) if (!strncmp(fn->name, name, namelen) && !fn->name[namelen]) break; if (!fn) { - char *namebuf; fn = xcalloc(1, sizeof(struct ll_merge_driver)); - namebuf = xmalloc(namelen + 1); - memcpy(namebuf, name, namelen); - namebuf[namelen] = 0; - fn->name = namebuf; + fn->name = xmemdupz(name, namelen); fn->fn = ll_ext_merge; - fn->next = NULL; *ll_user_merge_tail = fn; ll_user_merge_tail = &(fn->next); } diff --git a/refs.c b/refs.c index 7fb3350789..07e260c8a1 100644 --- a/refs.c +++ b/refs.c @@ -1246,15 +1246,11 @@ int create_symref(const char *ref_target, const char *refs_heads_master, static char *ref_msg(const char *line, const char *endp) { const char *ep; - char *msg; - line += 82; - for (ep = line; ep < endp && *ep != '\n'; ep++) - ; - msg = xmalloc(ep - line + 1); - memcpy(msg, line, ep - line); - msg[ep - line] = 0; - return msg; + ep = memchr(line, '\n', endp - line); + if (!ep) + ep = endp; + return xmemdupz(line, ep - line); } int read_ref_at(const char *ref, unsigned long at_time, int cnt, unsigned char *sha1, char **msg, unsigned long *cutoff_time, int *cutoff_tz, int *cutoff_cnt) diff --git a/sha1_file.c b/sha1_file.c index 59325d46be..385c5d891a 100644 --- a/sha1_file.c +++ b/sha1_file.c @@ -1491,11 +1491,8 @@ found_cache_entry: ent->lru.next->prev = ent->lru.prev; ent->lru.prev->next = ent->lru.next; delta_base_cached -= ent->size; - } - else { - ret = xmalloc(ent->size + 1); - memcpy(ret, ent->data, ent->size); - ((char *)ret)[ent->size] = 0; + } else { + ret = xmemdupz(ent->data, ent->size); } *type = ent->type; *base_size = ent->size; @@ -1872,12 +1869,9 @@ void *read_sha1_file(const unsigned char *sha1, enum object_type *type, co = find_cached_object(sha1); if (co) { - buf = xmalloc(co->size + 1); - memcpy(buf, co->buf, co->size); - ((char*)buf)[co->size] = 0; *type = co->type; *size = co->size; - return buf; + return xmemdupz(co->buf, co->size); } buf = read_packed_sha1(sha1, type, size); diff --git a/tag.c b/tag.c index bbacd59a23..f62bcdd994 100644 --- a/tag.c +++ b/tag.c @@ -68,9 +68,7 @@ int parse_tag_buffer(struct tag *item, void *data, unsigned long size) memcpy(type, type_line + 5, typelen); type[typelen] = '\0'; taglen = sig_line - tag_line - strlen("tag \n"); - item->tag = xmalloc(taglen + 1); - memcpy(item->tag, tag_line + 4, taglen); - item->tag[taglen] = '\0'; + item->tag = xmemdupz(tag_line + 4, taglen); if (!strcmp(type, blob_type)) { item->tagged = &lookup_blob(sha1)->object; -- cgit v1.2.3 From c76689df6c64a1e987bd779bd71a2042b5131fb9 Mon Sep 17 00:00:00 2001 From: Pierre Habouzit Date: Thu, 20 Sep 2007 00:42:12 +0200 Subject: strbuf API additions and enhancements. Add strbuf_remove, change strbuf_insert: As both are special cases of strbuf_splice, implement them as such. gcc is able to do the math and generate almost optimal code this way. Add strbuf_swap: Exchange the values of its arguments. Use it in fast-import.c Also fix spacing issues in strbuf.h Signed-off-by: Pierre Habouzit --- commit.c | 2 +- fast-import.c | 4 +--- strbuf.c | 20 ++++++++++---------- strbuf.h | 17 +++++++++++------ 4 files changed, 23 insertions(+), 20 deletions(-) (limited to 'commit.c') diff --git a/commit.c b/commit.c index f86fa776c0..55b08ec0b9 100644 --- a/commit.c +++ b/commit.c @@ -656,7 +656,7 @@ static char *replace_encoding_header(char *buf, const char *encoding) strbuf_attach(&tmp, buf, strlen(buf), strlen(buf) + 1); if (is_encoding_utf8(encoding)) { /* we have re-coded to UTF-8; drop the header */ - strbuf_splice(&tmp, start, len, NULL, 0); + strbuf_remove(&tmp, start, len); } else { /* just replaces XXXX in 'encoding XXXX\n' */ strbuf_splice(&tmp, start + strlen("encoding "), diff --git a/fast-import.c b/fast-import.c index f9906586ee..eddae22ea1 100644 --- a/fast-import.c +++ b/fast-import.c @@ -1111,9 +1111,7 @@ static int store_object( if (last->no_swap) { last->data = *dat; } else { - struct strbuf tmp = *dat; - *dat = last->data; - last->data = tmp; + strbuf_swap(&last->data, dat); } last->offset = e->offset; } diff --git a/strbuf.c b/strbuf.c index 59383ac776..dcb725dcdd 100644 --- a/strbuf.c +++ b/strbuf.c @@ -50,16 +50,6 @@ void strbuf_rtrim(struct strbuf *sb) sb->buf[sb->len] = '\0'; } -void strbuf_insert(struct strbuf *sb, size_t pos, const void *data, size_t len) -{ - strbuf_grow(sb, len); - if (pos > sb->len) - die("`pos' is too far after the end of the buffer"); - memmove(sb->buf + pos + len, sb->buf + pos, sb->len - pos); - memcpy(sb->buf + pos, data, len); - strbuf_setlen(sb, sb->len + len); -} - void strbuf_splice(struct strbuf *sb, size_t pos, size_t len, const void *data, size_t dlen) { @@ -79,6 +69,16 @@ void strbuf_splice(struct strbuf *sb, size_t pos, size_t len, strbuf_setlen(sb, sb->len + dlen - len); } +void strbuf_insert(struct strbuf *sb, size_t pos, const void *data, size_t len) +{ + strbuf_splice(sb, pos, 0, data, len); +} + +void strbuf_remove(struct strbuf *sb, size_t pos, size_t len) +{ + strbuf_splice(sb, pos, len, NULL, 0); +} + void strbuf_add(struct strbuf *sb, const void *data, size_t len) { strbuf_grow(sb, len); diff --git a/strbuf.h b/strbuf.h index b2cbd976f4..567e2d17d1 100644 --- a/strbuf.h +++ b/strbuf.h @@ -55,15 +55,20 @@ extern void strbuf_release(struct strbuf *); extern void strbuf_reset(struct strbuf *); extern char *strbuf_detach(struct strbuf *); extern void strbuf_attach(struct strbuf *, void *, size_t, size_t); +static inline void strbuf_swap(struct strbuf *a, struct strbuf *b) { + struct strbuf tmp = *a; + *a = *b; + *b = tmp; +} /*----- strbuf size related -----*/ static inline size_t strbuf_avail(struct strbuf *sb) { - return sb->alloc ? sb->alloc - sb->len - 1 : 0; + return sb->alloc ? sb->alloc - sb->len - 1 : 0; } static inline void strbuf_setlen(struct strbuf *sb, size_t len) { - assert (len < sb->alloc); - sb->len = len; - sb->buf[len] = '\0'; + assert (len < sb->alloc); + sb->len = len; + sb->buf[len] = '\0'; } extern void strbuf_grow(struct strbuf *, size_t); @@ -78,12 +83,12 @@ static inline void strbuf_addch(struct strbuf *sb, int c) { sb->buf[sb->len] = '\0'; } -/* inserts after pos, or appends if pos >= sb->len */ extern void strbuf_insert(struct strbuf *, size_t pos, const void *, size_t); +extern void strbuf_remove(struct strbuf *, size_t pos, size_t len); /* splice pos..pos+len with given data */ extern void strbuf_splice(struct strbuf *, size_t pos, size_t len, - const void *, size_t); + const void *, size_t); extern void strbuf_add(struct strbuf *, const void *, size_t); static inline void strbuf_addstr(struct strbuf *sb, const char *s) { -- cgit v1.2.3 From b315c5c08139c0d3c1e4867a305334e29da01d07 Mon Sep 17 00:00:00 2001 From: Pierre Habouzit Date: Thu, 27 Sep 2007 12:58:23 +0200 Subject: strbuf change: be sure ->buf is never ever NULL. For that purpose, the ->buf is always initialized with a char * buf living in the strbuf module. It is made a char * so that we can sloppily accept things that perform: sb->buf[0] = '\0', and because you can't pass "" as an initializer for ->buf without making gcc unhappy for very good reasons. strbuf_init/_detach/_grow have been fixed to trust ->alloc and not ->buf anymore. as a consequence strbuf_detach is _mandatory_ to detach a buffer, copying ->buf isn't an option anymore, if ->buf is going to escape from the scope, and eventually be free'd. API changes: * strbuf_setlen now always works, so just make strbuf_reset a convenience macro. * strbuf_detatch takes a size_t* optional argument (meaning it can be NULL) to copy the buffer's len, as it was needed for this refactor to make the code more readable, and working like the callers. Signed-off-by: Pierre Habouzit Signed-off-by: Junio C Hamano --- builtin-apply.c | 16 +++++++--------- builtin-archive.c | 5 ++--- builtin-fetch--tool.c | 2 +- commit.c | 2 +- convert.c | 4 ++-- diff.c | 14 ++++++-------- entry.c | 3 +-- fast-import.c | 2 +- imap-send.c | 2 +- quote.c | 2 +- sha1_file.c | 3 +-- strbuf.c | 30 +++++++++++++++++++----------- strbuf.h | 10 +++++----- 13 files changed, 48 insertions(+), 47 deletions(-) (limited to 'commit.c') diff --git a/builtin-apply.c b/builtin-apply.c index 01c9d60642..740623e6c0 100644 --- a/builtin-apply.c +++ b/builtin-apply.c @@ -178,14 +178,13 @@ static void say_patch_name(FILE *output, const char *pre, struct patch *patch, c #define CHUNKSIZE (8192) #define SLOP (16) -static void *read_patch_file(int fd, unsigned long *sizep) +static void *read_patch_file(int fd, size_t *sizep) { struct strbuf buf; strbuf_init(&buf, 0); if (strbuf_read(&buf, fd, 0) < 0) die("git-apply: read returned %s", strerror(errno)); - *sizep = buf.len; /* * Make sure that we have some slop in the buffer @@ -194,7 +193,7 @@ static void *read_patch_file(int fd, unsigned long *sizep) */ strbuf_grow(&buf, SLOP); memset(buf.buf + buf.len, 0, SLOP); - return strbuf_detach(&buf); + return strbuf_detach(&buf, sizep); } static unsigned long linelen(const char *buffer, unsigned long size) @@ -253,7 +252,7 @@ static char *find_name(const char *line, char *def, int p_value, int terminate) */ strbuf_remove(&name, 0, cp - name.buf); free(def); - return name.buf; + return strbuf_detach(&name, NULL); } } strbuf_release(&name); @@ -607,7 +606,7 @@ static char *git_header_name(char *line, int llen) if (strcmp(cp + 1, first.buf)) goto free_and_fail1; strbuf_release(&sp); - return first.buf; + return strbuf_detach(&first, NULL); } /* unquoted second */ @@ -618,7 +617,7 @@ static char *git_header_name(char *line, int llen) if (line + llen - cp != first.len + 1 || memcmp(first.buf, cp, first.len)) goto free_and_fail1; - return first.buf; + return strbuf_detach(&first, NULL); free_and_fail1: strbuf_release(&first); @@ -655,7 +654,7 @@ static char *git_header_name(char *line, int llen) isspace(name[len])) { /* Good */ strbuf_remove(&sp, 0, np - sp.buf); - return sp.buf; + return strbuf_detach(&sp, NULL); } free_and_fail2: @@ -1968,8 +1967,7 @@ static int apply_data(struct patch *patch, struct stat *st, struct cache_entry * if (apply_fragments(&buf, patch) < 0) return -1; /* note with --reject this succeeds. */ - patch->result = buf.buf; - patch->resultsize = buf.len; + patch->result = strbuf_detach(&buf, &patch->resultsize); if (0 < patch->is_delete && patch->resultsize) return error("removal patch leaves file contents"); diff --git a/builtin-archive.c b/builtin-archive.c index 843a9e37bb..04385dea05 100644 --- a/builtin-archive.c +++ b/builtin-archive.c @@ -89,7 +89,7 @@ static void format_subst(const struct commit *commit, struct strbuf fmt; if (src == buf->buf) - to_free = strbuf_detach(buf); + to_free = strbuf_detach(buf, NULL); strbuf_init(&fmt, 0); for (;;) { const char *b, *c; @@ -153,8 +153,7 @@ void *sha1_file_to_archive(const char *path, const unsigned char *sha1, strbuf_attach(&buf, buffer, *sizep, *sizep + 1); convert_to_working_tree(path, buf.buf, buf.len, &buf); convert_to_archive(path, buf.buf, buf.len, &buf, commit); - *sizep = buf.len; - buffer = buf.buf; + buffer = strbuf_detach(&buf, sizep); } return buffer; diff --git a/builtin-fetch--tool.c b/builtin-fetch--tool.c index 349b59c258..1e43d79221 100644 --- a/builtin-fetch--tool.c +++ b/builtin-fetch--tool.c @@ -10,7 +10,7 @@ static char *get_stdin(void) if (strbuf_read(&buf, 0, 1024) < 0) { die("error reading standard input: %s", strerror(errno)); } - return strbuf_detach(&buf); + return strbuf_detach(&buf, NULL); } static void show_new(enum object_type type, unsigned char *sha1_new) diff --git a/commit.c b/commit.c index 55b08ec0b9..62cc74d7a9 100644 --- a/commit.c +++ b/commit.c @@ -663,7 +663,7 @@ static char *replace_encoding_header(char *buf, const char *encoding) len - strlen("encoding \n"), encoding, strlen(encoding)); } - return tmp.buf; + return strbuf_detach(&tmp, NULL); } static char *logmsg_reencode(const struct commit *commit, diff --git a/convert.c b/convert.c index 79c9df2e91..0d5e909c69 100644 --- a/convert.c +++ b/convert.c @@ -168,7 +168,7 @@ static int crlf_to_worktree(const char *path, const char *src, size_t len, /* are we "faking" in place editing ? */ if (src == buf->buf) - to_free = strbuf_detach(buf); + to_free = strbuf_detach(buf, NULL); strbuf_grow(buf, len + stats.lf - stats.crlf); for (;;) { @@ -464,7 +464,7 @@ static int ident_to_worktree(const char *path, const char *src, size_t len, /* are we "faking" in place editing ? */ if (src == buf->buf) - to_free = strbuf_detach(buf); + to_free = strbuf_detach(buf, NULL); hash_sha1_file(src, len, "blob", sha1); strbuf_grow(buf, len + cnt * 43); diff --git a/diff.c b/diff.c index fb6d077f06..ab575191d1 100644 --- a/diff.c +++ b/diff.c @@ -197,7 +197,7 @@ static char *quote_two(const char *one, const char *two) strbuf_addstr(&res, one); strbuf_addstr(&res, two); } - return res.buf; + return strbuf_detach(&res, NULL); } static const char *external_diff(void) @@ -662,7 +662,7 @@ static char *pprint_rename(const char *a, const char *b) quote_c_style(a, &name, NULL, 0); strbuf_addstr(&name, " => "); quote_c_style(b, &name, NULL, 0); - return name.buf; + return strbuf_detach(&name, NULL); } /* Find common prefix */ @@ -710,7 +710,7 @@ static char *pprint_rename(const char *a, const char *b) strbuf_addch(&name, '}'); strbuf_add(&name, a + len_a - sfx_length, sfx_length); } - return name.buf; + return strbuf_detach(&name, NULL); } struct diffstat_t { @@ -827,7 +827,7 @@ static void show_stats(struct diffstat_t* data, struct diff_options *options) strbuf_init(&buf, 0); if (quote_c_style(file->name, &buf, NULL, 0)) { free(file->name); - file->name = buf.buf; + file->name = strbuf_detach(&buf, NULL); } else { strbuf_release(&buf); } @@ -1519,8 +1519,7 @@ static int populate_from_stdin(struct diff_filespec *s) strerror(errno)); s->should_munmap = 0; - s->size = buf.len; - s->data = strbuf_detach(&buf); + s->data = strbuf_detach(&buf, &s->size); s->should_free = 1; return 0; } @@ -1612,8 +1611,7 @@ int diff_populate_filespec(struct diff_filespec *s, int size_only) if (convert_to_git(s->path, s->data, s->size, &buf)) { munmap(s->data, s->size); s->should_munmap = 0; - s->data = buf.buf; - s->size = buf.len; + s->data = strbuf_detach(&buf, &s->size); s->should_free = 1; } } diff --git a/entry.c b/entry.c index 4a8c73bfae..98f5f6d4ec 100644 --- a/entry.c +++ b/entry.c @@ -120,8 +120,7 @@ static int write_entry(struct cache_entry *ce, char *path, const struct checkout strbuf_init(&buf, 0); if (convert_to_working_tree(ce->name, new, size, &buf)) { free(new); - new = buf.buf; - size = buf.len; + new = strbuf_detach(&buf, &size); } if (to_tempfile) { diff --git a/fast-import.c b/fast-import.c index a870a44e3d..e9c80be4cd 100644 --- a/fast-import.c +++ b/fast-import.c @@ -1562,7 +1562,7 @@ static int read_next_command(void) } else { struct recent_command *rc; - strbuf_detach(&command_buf); + strbuf_detach(&command_buf, NULL); stdin_eof = strbuf_getline(&command_buf, stdin, '\n'); if (stdin_eof) return EOF; diff --git a/imap-send.c b/imap-send.c index e95cdde062..a429a76a63 100644 --- a/imap-send.c +++ b/imap-send.c @@ -1180,7 +1180,7 @@ read_message( FILE *f, msg_data_t *msg ) } while (!feof(f)); msg->len = buf.len; - msg->data = strbuf_detach(&buf); + msg->data = strbuf_detach(&buf, NULL); return msg->len; } diff --git a/quote.c b/quote.c index 800fd88c9a..482be05b7a 100644 --- a/quote.c +++ b/quote.c @@ -22,7 +22,7 @@ void sq_quote_buf(struct strbuf *dst, const char *src) char *to_free = NULL; if (dst->buf == src) - to_free = strbuf_detach(dst); + to_free = strbuf_detach(dst, NULL); strbuf_addch(dst, '\''); while (*src) { diff --git a/sha1_file.c b/sha1_file.c index 385c5d891a..753742a47c 100644 --- a/sha1_file.c +++ b/sha1_file.c @@ -2340,8 +2340,7 @@ int index_fd(unsigned char *sha1, int fd, struct stat *st, int write_object, strbuf_init(&nbuf, 0); if (convert_to_git(path, buf, size, &nbuf)) { munmap(buf, size); - size = nbuf.len; - buf = nbuf.buf; + buf = strbuf_detach(&nbuf, &size); re_allocated = 1; } } diff --git a/strbuf.c b/strbuf.c index d1e338bfb6..0e431daa61 100644 --- a/strbuf.c +++ b/strbuf.c @@ -1,27 +1,33 @@ #include "cache.h" +/* + * Used as the default ->buf value, so that people can always assume + * buf is non NULL and ->buf is NUL terminated even for a freshly + * initialized strbuf. + */ +char strbuf_slopbuf[1]; + void strbuf_init(struct strbuf *sb, size_t hint) { - memset(sb, 0, sizeof(*sb)); + sb->alloc = sb->len = 0; + sb->buf = strbuf_slopbuf; if (hint) strbuf_grow(sb, hint); } void strbuf_release(struct strbuf *sb) { - free(sb->buf); - memset(sb, 0, sizeof(*sb)); -} - -void strbuf_reset(struct strbuf *sb) -{ - if (sb->len) - strbuf_setlen(sb, 0); + if (sb->alloc) { + free(sb->buf); + strbuf_init(sb, 0); + } } -char *strbuf_detach(struct strbuf *sb) +char *strbuf_detach(struct strbuf *sb, size_t *sz) { - char *res = sb->buf; + char *res = sb->alloc ? sb->buf : NULL; + if (sz) + *sz = sb->len; strbuf_init(sb, 0); return res; } @@ -40,6 +46,8 @@ void strbuf_grow(struct strbuf *sb, size_t extra) { if (sb->len + extra + 1 <= sb->len) die("you want to use way too much memory"); + if (!sb->alloc) + sb->buf = NULL; ALLOC_GROW(sb->buf, sb->len + extra + 1, sb->alloc); } diff --git a/strbuf.h b/strbuf.h index 5657e3db14..6deec78479 100644 --- a/strbuf.h +++ b/strbuf.h @@ -10,8 +10,7 @@ * 1. the ->buf member is always malloc-ed, hence strbuf's can be used to * build complex strings/buffers whose final size isn't easily known. * - * It is legal to copy the ->buf pointer away. Though if you want to reuse - * the strbuf after that, setting ->buf to NULL isn't legal. + * It is NOT legal to copy the ->buf pointer away. * `strbuf_detach' is the operation that detachs a buffer from its shell * while keeping the shell valid wrt its invariants. * @@ -41,19 +40,19 @@ #include +extern char strbuf_slopbuf[]; struct strbuf { size_t alloc; size_t len; char *buf; }; -#define STRBUF_INIT { 0, 0, NULL } +#define STRBUF_INIT { 0, 0, strbuf_slopbuf } /*----- strbuf life cycle -----*/ extern void strbuf_init(struct strbuf *, size_t); extern void strbuf_release(struct strbuf *); -extern void strbuf_reset(struct strbuf *); -extern char *strbuf_detach(struct strbuf *); +extern char *strbuf_detach(struct strbuf *, size_t *); extern void strbuf_attach(struct strbuf *, void *, size_t, size_t); static inline void strbuf_swap(struct strbuf *a, struct strbuf *b) { struct strbuf tmp = *a; @@ -75,6 +74,7 @@ static inline void strbuf_setlen(struct strbuf *sb, size_t len) { sb->len = len; sb->buf[len] = '\0'; } +#define strbuf_reset(sb) strbuf_setlen(sb, 0) /*----- content related -----*/ extern void strbuf_rtrim(struct strbuf *); -- cgit v1.2.3