Skip to content

Commit c33ddc2

Browse files
peffgitster
authored andcommitted
date: use strbufs in date-formatting functions
Many of the date functions write into fixed-size buffers. This is a minor pain, as we have to take special precautions, and frequently end up copying the result into a strbuf or heap-allocated buffer anyway (for which we sometimes use strcpy!). Let's instead teach parse_date, datestamp, etc to write to a strbuf. The obvious downside is that we might need to perform a heap allocation where we otherwise would not need to. However, it turns out that the only two new allocations required are: 1. In test-date.c, where we don't care about efficiency. 2. In determine_author_info, which is not performance critical (and where the use of a strbuf will help later refactoring). Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
1 parent ea5517f commit c33ddc2

File tree

6 files changed

+45
-48
lines changed

6 files changed

+45
-48
lines changed

builtin/commit.c

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -520,19 +520,16 @@ static int sane_ident_split(struct ident_split *person)
520520
return 1;
521521
}
522522

523-
static int parse_force_date(const char *in, char *out, int len)
523+
static int parse_force_date(const char *in, struct strbuf *out)
524524
{
525-
if (len < 1)
526-
return -1;
527-
*out++ = '@';
528-
len--;
525+
strbuf_addch(out, '@');
529526

530-
if (parse_date(in, out, len) < 0) {
527+
if (parse_date(in, out) < 0) {
531528
int errors = 0;
532529
unsigned long t = approxidate_careful(in, &errors);
533530
if (errors)
534531
return -1;
535-
snprintf(out, len, "%lu", t);
532+
strbuf_addf(out, "%lu", t);
536533
}
537534

538535
return 0;
@@ -542,7 +539,7 @@ static void determine_author_info(struct strbuf *author_ident)
542539
{
543540
char *name, *email, *date;
544541
struct ident_split author;
545-
char date_buf[64];
542+
struct strbuf date_buf = STRBUF_INIT;
546543

547544
name = getenv("GIT_AUTHOR_NAME");
548545
email = getenv("GIT_AUTHOR_EMAIL");
@@ -588,9 +585,10 @@ static void determine_author_info(struct strbuf *author_ident)
588585
}
589586

590587
if (force_date) {
591-
if (parse_force_date(force_date, date_buf, sizeof(date_buf)))
588+
strbuf_reset(&date_buf);
589+
if (parse_force_date(force_date, &date_buf))
592590
die(_("invalid date format: %s"), force_date);
593-
date = date_buf;
591+
date = date_buf.buf;
594592
}
595593

596594
strbuf_addstr(author_ident, fmt_ident(name, email, date, IDENT_STRICT));
@@ -600,6 +598,8 @@ static void determine_author_info(struct strbuf *author_ident)
600598
export_one("GIT_AUTHOR_EMAIL", author.mail_begin, author.mail_end, 0);
601599
export_one("GIT_AUTHOR_DATE", author.date_begin, author.tz_end, '@');
602600
}
601+
602+
strbuf_release(&date_buf);
603603
}
604604

605605
static void split_ident_or_die(struct ident_split *id, const struct strbuf *buf)

cache.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1044,10 +1044,10 @@ enum date_mode {
10441044
const char *show_date(unsigned long time, int timezone, enum date_mode mode);
10451045
void show_date_relative(unsigned long time, int tz, const struct timeval *now,
10461046
struct strbuf *timebuf);
1047-
int parse_date(const char *date, char *buf, int bufsize);
1047+
int parse_date(const char *date, struct strbuf *out);
10481048
int parse_date_basic(const char *date, unsigned long *timestamp, int *offset);
10491049
int parse_expiry_date(const char *date, unsigned long *timestamp);
1050-
void datestamp(char *buf, int bufsize);
1050+
void datestamp(struct strbuf *out);
10511051
#define approxidate(s) approxidate_careful((s), NULL)
10521052
unsigned long approxidate_careful(const char *, int *);
10531053
unsigned long approxidate_relative(const char *date, const struct timeval *now);

date.c

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -605,15 +605,15 @@ static int match_tz(const char *date, int *offp)
605605
return end - date;
606606
}
607607

608-
static int date_string(unsigned long date, int offset, char *buf, int len)
608+
static void date_string(unsigned long date, int offset, struct strbuf *buf)
609609
{
610610
int sign = '+';
611611

612612
if (offset < 0) {
613613
offset = -offset;
614614
sign = '-';
615615
}
616-
return snprintf(buf, len, "%lu %c%02d%02d", date, sign, offset / 60, offset % 60);
616+
strbuf_addf(buf, "%lu %c%02d%02d", date, sign, offset / 60, offset % 60);
617617
}
618618

619619
/*
@@ -735,13 +735,14 @@ int parse_expiry_date(const char *date, unsigned long *timestamp)
735735
return errors;
736736
}
737737

738-
int parse_date(const char *date, char *result, int maxlen)
738+
int parse_date(const char *date, struct strbuf *result)
739739
{
740740
unsigned long timestamp;
741741
int offset;
742742
if (parse_date_basic(date, &timestamp, &offset))
743743
return -1;
744-
return date_string(timestamp, offset, result, maxlen);
744+
date_string(timestamp, offset, result);
745+
return 0;
745746
}
746747

747748
enum date_mode parse_date_format(const char *format)
@@ -766,7 +767,7 @@ enum date_mode parse_date_format(const char *format)
766767
die("unknown date format %s", format);
767768
}
768769

769-
void datestamp(char *buf, int bufsize)
770+
void datestamp(struct strbuf *out)
770771
{
771772
time_t now;
772773
int offset;
@@ -776,7 +777,7 @@ void datestamp(char *buf, int bufsize)
776777
offset = tm_to_time_t(localtime(&now)) - now;
777778
offset /= 60;
778779

779-
date_string(now, offset, buf, bufsize);
780+
date_string(now, offset, out);
780781
}
781782

782783
/*

fast-import.c

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1971,7 +1971,7 @@ static int parse_data(struct strbuf *sb, uintmax_t limit, uintmax_t *len_res)
19711971
return 1;
19721972
}
19731973

1974-
static int validate_raw_date(const char *src, char *result, int maxlen)
1974+
static int validate_raw_date(const char *src, struct strbuf *result)
19751975
{
19761976
const char *orig_src = src;
19771977
char *endp;
@@ -1989,19 +1989,18 @@ static int validate_raw_date(const char *src, char *result, int maxlen)
19891989
return -1;
19901990

19911991
num = strtoul(src + 1, &endp, 10);
1992-
if (errno || endp == src + 1 || *endp || (endp - orig_src) >= maxlen ||
1993-
1400 < num)
1992+
if (errno || endp == src + 1 || *endp || 1400 < num)
19941993
return -1;
19951994

1996-
strcpy(result, orig_src);
1995+
strbuf_addstr(result, orig_src);
19971996
return 0;
19981997
}
19991998

20001999
static char *parse_ident(const char *buf)
20012000
{
20022001
const char *ltgt;
20032002
size_t name_len;
2004-
char *ident;
2003+
struct strbuf ident = STRBUF_INIT;
20052004

20062005
/* ensure there is a space delimiter even if there is no name */
20072006
if (*buf == '<')
@@ -2020,26 +2019,25 @@ static char *parse_ident(const char *buf)
20202019
die("Missing space after > in ident string: %s", buf);
20212020
ltgt++;
20222021
name_len = ltgt - buf;
2023-
ident = xmalloc(name_len + 24);
2024-
strncpy(ident, buf, name_len);
2022+
strbuf_add(&ident, buf, name_len);
20252023

20262024
switch (whenspec) {
20272025
case WHENSPEC_RAW:
2028-
if (validate_raw_date(ltgt, ident + name_len, 24) < 0)
2026+
if (validate_raw_date(ltgt, &ident) < 0)
20292027
die("Invalid raw date \"%s\" in ident: %s", ltgt, buf);
20302028
break;
20312029
case WHENSPEC_RFC2822:
2032-
if (parse_date(ltgt, ident + name_len, 24) < 0)
2030+
if (parse_date(ltgt, &ident) < 0)
20332031
die("Invalid rfc2822 date \"%s\" in ident: %s", ltgt, buf);
20342032
break;
20352033
case WHENSPEC_NOW:
20362034
if (strcmp("now", ltgt))
20372035
die("Date in ident must be 'now': %s", buf);
2038-
datestamp(ident + name_len, 24);
2036+
datestamp(&ident);
20392037
break;
20402038
}
20412039

2042-
return ident;
2040+
return strbuf_detach(&ident, NULL);
20432041
}
20442042

20452043
static void parse_and_store_blob(

ident.c

Lines changed: 11 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99

1010
static struct strbuf git_default_name = STRBUF_INIT;
1111
static struct strbuf git_default_email = STRBUF_INIT;
12-
static char git_default_date[50];
12+
static struct strbuf git_default_date = STRBUF_INIT;
1313

1414
#define IDENT_NAME_GIVEN 01
1515
#define IDENT_MAIL_GIVEN 02
@@ -129,9 +129,9 @@ const char *ident_default_email(void)
129129

130130
static const char *ident_default_date(void)
131131
{
132-
if (!git_default_date[0])
133-
datestamp(git_default_date, sizeof(git_default_date));
134-
return git_default_date;
132+
if (!git_default_date.len)
133+
datestamp(&git_default_date);
134+
return git_default_date.buf;
135135
}
136136

137137
static int crud(unsigned char c)
@@ -292,7 +292,6 @@ const char *fmt_ident(const char *name, const char *email,
292292
const char *date_str, int flag)
293293
{
294294
static struct strbuf ident = STRBUF_INIT;
295-
char date[50];
296295
int strict = (flag & IDENT_STRICT);
297296
int want_date = !(flag & IDENT_NO_DATE);
298297
int want_name = !(flag & IDENT_NO_NAME);
@@ -320,15 +319,6 @@ const char *fmt_ident(const char *name, const char *email,
320319
die("unable to auto-detect email address (got '%s')", email);
321320
}
322321

323-
if (want_date) {
324-
if (date_str && date_str[0]) {
325-
if (parse_date(date_str, date, sizeof(date)) < 0)
326-
die("invalid date format: %s", date_str);
327-
}
328-
else
329-
strcpy(date, ident_default_date());
330-
}
331-
332322
strbuf_reset(&ident);
333323
if (want_name) {
334324
strbuf_addstr_without_crud(&ident, name);
@@ -339,8 +329,14 @@ const char *fmt_ident(const char *name, const char *email,
339329
strbuf_addch(&ident, '>');
340330
if (want_date) {
341331
strbuf_addch(&ident, ' ');
342-
strbuf_addstr_without_crud(&ident, date);
332+
if (date_str && date_str[0]) {
333+
if (parse_date(date_str, &ident) < 0)
334+
die("invalid date format: %s", date_str);
335+
}
336+
else
337+
strbuf_addstr(&ident, ident_default_date());
343338
}
339+
344340
return ident.buf;
345341
}
346342

test-date.c

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,19 +19,21 @@ static void show_dates(char **argv, struct timeval *now)
1919

2020
static void parse_dates(char **argv, struct timeval *now)
2121
{
22+
struct strbuf result = STRBUF_INIT;
23+
2224
for (; *argv; argv++) {
23-
char result[100];
2425
unsigned long t;
2526
int tz;
2627

27-
result[0] = 0;
28-
parse_date(*argv, result, sizeof(result));
29-
if (sscanf(result, "%lu %d", &t, &tz) == 2)
28+
strbuf_reset(&result);
29+
parse_date(*argv, &result);
30+
if (sscanf(result.buf, "%lu %d", &t, &tz) == 2)
3031
printf("%s -> %s\n",
3132
*argv, show_date(t, tz, DATE_ISO8601));
3233
else
3334
printf("%s -> bad\n", *argv);
3435
}
36+
strbuf_release(&result);
3537
}
3638

3739
static void parse_approxidate(char **argv, struct timeval *now)

0 commit comments

Comments
 (0)