[PATCH 1/6] Strbuf API extensions and fixes.

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



  * Add strbuf_rtrim to remove trailing spaces.
  * Add strbuf_insert to insert data at a given position.
  * Off-by one fix in strbuf_addf: strbuf_avail() does not counts the final
    \0 so the overflow test for snprintf is the strict comparison. This is
    not critical as the growth mechanism chosen will always allocate _more_
    memory than asked, so the second test will not fail. It's some kind of
    miracle though.
  * Add size extension hints for strbuf_init and strbuf_read. If 0, default
    applies, else:
      + initial buffer has the given size for strbuf_init.
      + first growth checks it has at least this size rather than the
        default 8192.

Signed-off-by: Pierre Habouzit <madcoder@xxxxxxxxxx>
---
 archive-tar.c            |    4 ++--
 builtin-apply.c          |    4 ++--
 builtin-blame.c          |    6 +++---
 builtin-checkout-index.c |    2 +-
 builtin-commit-tree.c    |    5 ++---
 builtin-rerere.c         |    4 ++--
 builtin-update-index.c   |    4 ++--
 cache-tree.c             |    5 ++---
 diff.c                   |    4 ++--
 fast-import.c            |    4 ++--
 fetch.c                  |    2 +-
 mktree.c                 |    5 ++---
 strbuf.c                 |   33 +++++++++++++++++++++++++++------
 strbuf.h                 |   10 ++++++++--
 14 files changed, 58 insertions(+), 34 deletions(-)

diff --git a/archive-tar.c b/archive-tar.c
index 0612bb6..cc94cf3 100644
--- a/archive-tar.c
+++ b/archive-tar.c
@@ -132,7 +132,7 @@ static void write_entry(const unsigned char *sha1, struct strbuf *path,
 	struct strbuf ext_header;
 
 	memset(&header, 0, sizeof(header));
-	strbuf_init(&ext_header);
+	strbuf_init(&ext_header, 0);
 
 	if (!sha1) {
 		*header.typeflag = TYPEFLAG_GLOBAL_HEADER;
@@ -214,7 +214,7 @@ static void write_global_extended_header(const unsigned char *sha1)
 {
 	struct strbuf ext_header;
 
-	strbuf_init(&ext_header);
+	strbuf_init(&ext_header, 0);
 	strbuf_append_ext_header(&ext_header, "comment", sha1_to_hex(sha1), 40);
 	write_entry(NULL, NULL, 0, ext_header.buf, ext_header.len);
 	strbuf_release(&ext_header);
diff --git a/builtin-apply.c b/builtin-apply.c
index 90e328e..988e85f 100644
--- a/builtin-apply.c
+++ b/builtin-apply.c
@@ -184,8 +184,8 @@ static void *read_patch_file(int fd, unsigned long *sizep)
 {
 	struct strbuf buf;
 
-	strbuf_init(&buf);
-	if (strbuf_read(&buf, fd) < 0)
+	strbuf_init(&buf, 0);
+	if (strbuf_read(&buf, fd, 0) < 0)
 		die("git-apply: read returned %s", strerror(errno));
 	*sizep = buf.len;
 
diff --git a/builtin-blame.c b/builtin-blame.c
index 1b1e6da..b004f06 100644
--- a/builtin-blame.c
+++ b/builtin-blame.c
@@ -2023,7 +2023,7 @@ static struct commit *fake_working_tree_commit(const char *path, const char *con
 
 	origin = make_origin(commit, path);
 
-	strbuf_init(&buf);
+	strbuf_init(&buf, 0);
 	if (!contents_from || strcmp("-", contents_from)) {
 		struct stat st;
 		const char *read_from;
@@ -2046,7 +2046,7 @@ static struct commit *fake_working_tree_commit(const char *path, const char *con
 			fd = open(read_from, O_RDONLY);
 			if (fd < 0)
 				die("cannot open %s", read_from);
-			if (strbuf_read(&buf, fd) != xsize_t(st.st_size))
+			if (strbuf_read(&buf, fd, 0) != xsize_t(st.st_size))
 				die("cannot read %s", read_from);
 			break;
 		case S_IFLNK:
@@ -2062,7 +2062,7 @@ static struct commit *fake_working_tree_commit(const char *path, const char *con
 		/* Reading from stdin */
 		contents_from = "standard input";
 		mode = 0;
-		if (strbuf_read(&buf, 0) < 0)
+		if (strbuf_read(&buf, 0, 0) < 0)
 			die("read error %s from stdin", strerror(errno));
 	}
 	origin->file.ptr = buf.buf;
diff --git a/builtin-checkout-index.c b/builtin-checkout-index.c
index 75377b9..153ba7d 100644
--- a/builtin-checkout-index.c
+++ b/builtin-checkout-index.c
@@ -274,7 +274,7 @@ int cmd_checkout_index(int argc, const char **argv, const char *prefix)
 		struct strbuf buf;
 		if (all)
 			die("git-checkout-index: don't mix '--all' and '--stdin'");
-		strbuf_init(&buf);
+		strbuf_init(&buf, 0);
 		while (1) {
 			char *path_name;
 			const char *p;
diff --git a/builtin-commit-tree.c b/builtin-commit-tree.c
index bc9502c..325334f 100644
--- a/builtin-commit-tree.c
+++ b/builtin-commit-tree.c
@@ -87,8 +87,7 @@ int cmd_commit_tree(int argc, const char **argv, const char *prefix)
 	/* Not having i18n.commitencoding is the same as having utf-8 */
 	encoding_is_utf8 = is_encoding_utf8(git_commit_encoding);
 
-	strbuf_init(&buffer);
-	strbuf_grow(&buffer, 8192); /* should avoid reallocs for the headers */
+	strbuf_init(&buffer, 8192); /* should avoid reallocs for the headers */
 	strbuf_addf(&buffer, "tree %s\n", sha1_to_hex(tree_sha1));
 
 	/*
@@ -107,7 +106,7 @@ int cmd_commit_tree(int argc, const char **argv, const char *prefix)
 	strbuf_addch(&buffer, '\n');
 
 	/* And add the comment */
-	if (strbuf_read(&buffer, 0) < 0)
+	if (strbuf_read(&buffer, 0, 0) < 0)
 		die("git-commit-tree: read returned %s", strerror(errno));
 
 	/* And check the encoding */
diff --git a/builtin-rerere.c b/builtin-rerere.c
index 98d7702..826d346 100644
--- a/builtin-rerere.c
+++ b/builtin-rerere.c
@@ -78,8 +78,8 @@ static int handle_file(const char *path,
 	FILE *f = fopen(path, "r");
 	FILE *out;
 
-	strbuf_init(&minus);
-	strbuf_init(&plus);
+	strbuf_init(&minus, 0);
+	strbuf_init(&plus,  0);
 
 	if (!f)
 		return error("Could not open %s", path);
diff --git a/builtin-update-index.c b/builtin-update-index.c
index a7a4574..9240a28 100644
--- a/builtin-update-index.c
+++ b/builtin-update-index.c
@@ -303,7 +303,7 @@ static void update_one(const char *path, const char *prefix, int prefix_length)
 static void read_index_info(int line_termination)
 {
 	struct strbuf buf;
-	strbuf_init(&buf);
+	strbuf_init(&buf, 0);
 	while (1) {
 		char *ptr, *tab;
 		char *path_name;
@@ -716,7 +716,7 @@ int cmd_update_index(int argc, const char **argv, const char *prefix)
 	}
 	if (read_from_stdin) {
 		struct strbuf buf;
-		strbuf_init(&buf);
+		strbuf_init(&buf, 0);
 		while (1) {
 			char *path_name;
 			const char *p;
diff --git a/cache-tree.c b/cache-tree.c
index 76af6f5..8f53c99 100644
--- a/cache-tree.c
+++ b/cache-tree.c
@@ -293,8 +293,7 @@ static int update_one(struct cache_tree *it,
 	/*
 	 * Then write out the tree object for this level.
 	 */
-	strbuf_init(&buffer);
-	strbuf_grow(&buffer, 8192);
+	strbuf_init(&buffer, 8192);
 
 	for (i = 0; i < entries; i++) {
 		struct cache_entry *ce = cache[i];
@@ -419,7 +418,7 @@ void *cache_tree_write(struct cache_tree *root, unsigned long *size_p)
 	struct strbuf buffer;
 
 	path[0] = 0;
-	strbuf_init(&buffer);
+	strbuf_init(&buffer, 0);
 	write_one(root, path, 0, &buffer);
 	*size_p = buffer.len;
 	return strbuf_detach(&buffer);
diff --git a/diff.c b/diff.c
index 26d7bb9..7290309 100644
--- a/diff.c
+++ b/diff.c
@@ -1548,8 +1548,8 @@ static int populate_from_stdin(struct diff_filespec *s)
 {
 	struct strbuf buf;
 
-	strbuf_init(&buf);
-	if (strbuf_read(&buf, 0) < 0)
+	strbuf_init(&buf, 0);
+	if (strbuf_read(&buf, 0, 0) < 0)
 		return error("error while reading from stdin %s",
 				     strerror(errno));
 
diff --git a/fast-import.c b/fast-import.c
index 74ff0fd..2c0bfb9 100644
--- a/fast-import.c
+++ b/fast-import.c
@@ -1640,7 +1640,7 @@ static void *cmd_data (size_t *size)
 {
 	struct strbuf buffer;
 
-	strbuf_init(&buffer);
+	strbuf_init(&buffer, 0);
 	if (prefixcmp(command_buf.buf, "data "))
 		die("Expected 'data n' command, found: %s", command_buf.buf);
 
@@ -2318,7 +2318,7 @@ int main(int argc, const char **argv)
 
 	git_config(git_default_config);
 	alloc_objects(object_entry_alloc);
-	strbuf_init(&command_buf);
+	strbuf_init(&command_buf, 0);
 	atom_table = xcalloc(atom_table_sz, sizeof(struct atom_str*));
 	branch_table = xcalloc(branch_table_sz, sizeof(struct branch*));
 	avail_tree_table = xcalloc(avail_tree_table_sz, sizeof(struct avail_tree_content*));
diff --git a/fetch.c b/fetch.c
index 811be87..dd6ed9e 100644
--- a/fetch.c
+++ b/fetch.c
@@ -218,7 +218,7 @@ int pull_targets_stdin(char ***target, const char ***write_ref)
 	int targets = 0, targets_alloc = 0;
 	struct strbuf buf;
 	*target = NULL; *write_ref = NULL;
-	strbuf_init(&buf);
+	strbuf_init(&buf, 0);
 	while (1) {
 		char *rf_one = NULL;
 		char *tg_one;
diff --git a/mktree.c b/mktree.c
index 2e84889..3891cd9 100644
--- a/mktree.c
+++ b/mktree.c
@@ -51,9 +51,8 @@ static void write_tree(unsigned char *sha1)
 	qsort(entries, used, sizeof(*entries), ent_compare);
 	for (size = i = 0; i < used; i++)
 		size += 32 + entries[i]->len;
-	strbuf_init(&buf);
-	strbuf_grow(&buf, size);
 
+	strbuf_init(&buf, size);
 	for (i = 0; i < used; i++) {
 		struct treeent *ent = entries[i];
 		strbuf_addf(&buf, "%o %s%c", ent->mode, ent->name, '\0');
@@ -83,7 +82,7 @@ int main(int ac, char **av)
 		av++;
 	}
 
-	strbuf_init(&sb);
+	strbuf_init(&sb, 0);
 	while (1) {
 		char *ptr, *ntr;
 		unsigned mode;
diff --git a/strbuf.c b/strbuf.c
index 7136de1..d919047 100644
--- a/strbuf.c
+++ b/strbuf.c
@@ -1,8 +1,10 @@
 #include "cache.h"
 #include "strbuf.h"
 
-void strbuf_init(struct strbuf *sb) {
+void strbuf_init(struct strbuf *sb, size_t hint) {
 	memset(sb, 0, sizeof(*sb));
+	if (hint)
+		strbuf_grow(sb, hint);
 }
 
 void strbuf_release(struct strbuf *sb) {
@@ -18,7 +20,7 @@ void strbuf_reset(struct strbuf *sb) {
 
 char *strbuf_detach(struct strbuf *sb) {
 	char *res = sb->buf;
-	strbuf_init(sb);
+	strbuf_init(sb, 0);
 	return res;
 }
 
@@ -28,6 +30,24 @@ void strbuf_grow(struct strbuf *sb, size_t extra) {
 	ALLOC_GROW(sb->buf, sb->len + extra + 1, sb->alloc);
 }
 
+void strbuf_rtrim(struct strbuf *sb)
+{
+	while (sb->len > 0 && isspace((unsigned char)sb->buf[sb->len - 1]))
+		sb->len--;
+	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) {
+		pos = sb->len;
+	} else {
+		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_add(struct strbuf *sb, const void *data, size_t len) {
 	strbuf_grow(sb, len);
 	memcpy(sb->buf + sb->len, data, len);
@@ -44,12 +64,12 @@ void strbuf_addf(struct strbuf *sb, const char *fmt, ...) {
 	if (len < 0) {
 		len = 0;
 	}
-	if (len >= strbuf_avail(sb)) {
+	if (len > strbuf_avail(sb)) {
 		strbuf_grow(sb, len);
 		va_start(ap, fmt);
 		len = vsnprintf(sb->buf + sb->len, sb->alloc - sb->len, fmt, ap);
 		va_end(ap);
-		if (len >= strbuf_avail(sb)) {
+		if (len > strbuf_avail(sb)) {
 			die("this should not happen, your snprintf is broken");
 		}
 	}
@@ -67,14 +87,14 @@ size_t strbuf_fread(struct strbuf *sb, size_t size, FILE *f) {
 	return res;
 }
 
-ssize_t strbuf_read(struct strbuf *sb, int fd)
+ssize_t strbuf_read(struct strbuf *sb, int fd, size_t hint)
 {
 	size_t oldlen = sb->len;
 
+	strbuf_grow(sb, hint ? hint : 8192);
 	for (;;) {
 		ssize_t cnt;
 
-		strbuf_grow(sb, 8192);
 		cnt = xread(fd, sb->buf + sb->len, sb->alloc - sb->len - 1);
 		if (cnt < 0) {
 			strbuf_setlen(sb, oldlen);
@@ -83,6 +103,7 @@ ssize_t strbuf_read(struct strbuf *sb, int fd)
 		if (!cnt)
 			break;
 		sb->len += cnt;
+		strbuf_grow(sb, 8192);
 	}
 
 	sb->buf[sb->len] = '\0';
diff --git a/strbuf.h b/strbuf.h
index b40dc99..21fc111 100644
--- a/strbuf.h
+++ b/strbuf.h
@@ -51,7 +51,7 @@ struct strbuf {
 #define STRBUF_INIT  { 0, 0, 0, NULL }
 
 /*----- strbuf life cycle -----*/
-extern void strbuf_init(struct strbuf *);
+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 *);
@@ -68,6 +68,9 @@ static inline void strbuf_setlen(struct strbuf *sb, size_t len) {
 
 extern void strbuf_grow(struct strbuf *, size_t);
 
+/*----- content related -----*/
+extern void strbuf_rtrim(struct strbuf *);
+
 /*----- add data in your buffer -----*/
 static inline void strbuf_addch(struct strbuf *sb, int c) {
 	strbuf_grow(sb, 1);
@@ -75,6 +78,9 @@ 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_add(struct strbuf *, const void *, size_t);
 static inline void strbuf_addstr(struct strbuf *sb, const char *s) {
 	strbuf_add(sb, s, strlen(s));
@@ -88,7 +94,7 @@ extern void strbuf_addf(struct strbuf *sb, const char *fmt, ...);
 
 extern size_t strbuf_fread(struct strbuf *, size_t, FILE *);
 /* XXX: if read fails, any partial read is undone */
-extern ssize_t strbuf_read(struct strbuf *, int fd);
+extern ssize_t strbuf_read(struct strbuf *, int fd, size_t hint);
 
 extern void read_line(struct strbuf *, FILE *, int);
 
-- 
1.5.3.1

-
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Linux Kernel Development]     [Gcc Help]     [IETF Annouce]     [DCCP]     [Netdev]     [Networking]     [Security]     [V4L]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux SCSI]     [Fedora Users]

  Powered by Linux