зеркало из https://github.com/microsoft/git.git
Strbuf API extensions and fixes.
* 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@debian.org> Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
Родитель
ddb95de33e
Коммит
f1696ee398
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
4
diff.c
4
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));
|
||||
|
||||
|
|
|
@ -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*));
|
||||
|
|
2
fetch.c
2
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;
|
||||
|
|
5
mktree.c
5
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;
|
||||
|
|
33
strbuf.c
33
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';
|
||||
|
|
10
strbuf.h
10
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);
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче