git.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Eric Sunshine <sunshine@sunshineco.com>
To: Jeff King <peff@peff.net>
Cc: "H.Merijn Brand" <h.m.brand@xs4all.nl>, git@vger.kernel.org
Subject: Re: [PATCH 3/3] introduce "format" date-mode
Date: Mon, 29 Jun 2015 18:22:47 -0400	[thread overview]
Message-ID: <20150629222247.GA31607@flurp.local> (raw)
In-Reply-To: <20150625165545.GC23503@peff.net>

On Thu, Jun 25, 2015 at 12:55:45PM -0400, Jeff King wrote:
> This feeds the format directly to strftime. Besides being a
> little more flexible, the main advantage is that your system
> strftime may know more about your locale's preferred format
> (e.g., how to spell the days of the week).
> 
> Signed-off-by: Jeff King <peff@peff.net>
> ---
> diff --git a/strbuf.c b/strbuf.c
> index 0d4f4e5..a7ba028 100644
> --- a/strbuf.c
> +++ b/strbuf.c
> @@ -709,3 +709,32 @@ char *xstrfmt(const char *fmt, ...)
> +void strbuf_addftime(struct strbuf *sb, const char *fmt, const struct tm *tm)
> +{
> +	size_t len;
> +
> +	/*
> +	 * strftime reports "0" if it could not fit the result in the buffer.
> +	 * Unfortunately, it also reports "0" if the requested time string
> +	 * takes 0 bytes. So if we were to probe and grow, we have to choose
> +	 * some arbitrary cap beyond which we guess that the format probably
> +	 * just results in a 0-length output. Since we have to choose some
> +	 * reasonable cap anyway, and since it is not that big, we may
> +	 * as well just grow to their in the first place.
> +	 */
> +	strbuf_grow(sb, 128);
> +	len = strftime(sb->buf + sb->len, sb->alloc - sb->len, fmt, tm);
> +
> +	if (!len) {
> +		/*
> +		 * Either we failed, or the format actually produces a 0-length
> +		 * output. There's not much we can do, so we leave it blank.
> +		 * However, the output array is left in an undefined state, so
> +		 * we must re-assert our NUL terminator.
> +		 */
> +		sb->buf[sb->len] = '\0';
> +	} else {
> +		sb->len += len;
> +	}
> +}

Clients of strbuf rightly expect the buffer to grow as needed in
order to complete the requested operation. It is, therefore, both
weird and expectation-breaking for strbuf_addftime() to lack this
behavior. Worse, it doesn't even signal when the format has failed
due to insufficient buffer space.

How about taking this approach (or something similar), instead, which
grows the strbuf as needed?

--- 8< ---
void strbuf_addftime(struct strbuf *sb, const char *fmt, const struct tm *tm)
{
	size_t len;
	struct strbuf f = STRBUF_INIT;

	/*
	 * This is a bit tricky since strftime returns 0 if the result did not
	 * fit in the supplied buffer, as well as when the formatted time has
	 * zero length. In the former case, we need to grow the buffer and try
	 * again. To distinguish between the two cases, we supply strftime with
	 * a format string one character longer than what the client supplied,
	 * which ensures that a successful format will have non-zero length,
	 * and then drop the extra character from the formatted time before
	 * returning.
	 */
	strbuf_addf(&f, "%s ", fmt);

	do {
		strbuf_grow(sb, 128);
		len = strftime(sb->buf + sb->len, sb->alloc - sb->len,
			       f.buf, tm);
	} while (!len);
	strbuf_setlen(sb, sb->len + len - 1);

	strbuf_release(&f);
}
--- 8< ---

If this is performance critical code, then the augmented format
string can be constructed with less expensive functions than
strbuf_addf().

  reply	other threads:[~2015-06-29 22:23 UTC|newest]

Thread overview: 31+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-06-25 11:19 several date related issues H.Merijn Brand
2015-06-25 12:44 ` Jeff King
2015-06-25 12:56   ` H.Merijn Brand
2015-06-25 16:53     ` [PATCH 0/3] localized date format Jeff King
2015-06-25 16:54       ` [PATCH 1/3] show-branch: use DATE_RELATIVE instead of magic number Jeff King
2015-06-25 16:55       ` [PATCH 2/3] convert "enum date_mode" into a struct Jeff King
2015-06-25 17:03         ` John Keeping
2015-06-25 17:22           ` Jeff King
2015-07-07 20:37         ` Junio C Hamano
2015-07-07 20:48           ` Jeff King
2015-07-07 21:05             ` Junio C Hamano
2015-07-07 21:13               ` Jeff King
2015-07-07 21:19                 ` Junio C Hamano
2015-06-25 16:55       ` [PATCH 3/3] introduce "format" date-mode Jeff King
2015-06-29 22:22         ` Eric Sunshine [this message]
2015-06-30 10:20           ` Jeff King
2015-06-30 16:22             ` Junio C Hamano
2015-06-30 17:50               ` Jeff King
2015-06-30 19:23                 ` Junio C Hamano
2015-06-30 19:33                   ` Jeff King
2015-06-30 16:58             ` Eric Sunshine
2015-06-30 17:58               ` Jeff King
2015-06-30 18:13                 ` Eric Sunshine
2015-06-30 19:22                   ` Jeff King
2015-06-30 17:05             ` Junio C Hamano
2015-06-30 17:48               ` Eric Sunshine
2015-06-30 19:17               ` Jeff King
2015-06-30 13:26           ` Jeff King
2015-06-30 17:05             ` Eric Sunshine
2015-07-21  0:41             ` Eric Sunshine
2015-07-21  1:19               ` Jeff King

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20150629222247.GA31607@flurp.local \
    --to=sunshine@sunshineco.com \
    --cc=git@vger.kernel.org \
    --cc=h.m.brand@xs4all.nl \
    --cc=peff@peff.net \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).