Subject: [PATCH v3 2/2] strbuf: change an always NULL/"" strbuf_addftime() param to bool

From: Ævar Arnfjörð Bjarmason <[email-masked]>
Date: Sat, 24 Jun 2017 11:36:35 +0000

Change the code for deciding what's to be done about %Z to stop
passing always either a NULL or "" char * to
strbuf_addftime(). Instead pass a boolean int to indicate whether the
strftime() %Z format should be suppressed by converting it to an empty
string, which is what this code is actually doing.

This code grew organically between the changes in 9eafe86d58 ("Merge
branch 'rs/strbuf-addftime-zZ'", 2017-06-22). The intent was to use
this API in the future to pass a custom leave the door open to pass a
custom timezone name to the function (see my [1] and related
messages).

But that's not what this code does now, and this strbuf_addstr() call
always being redundant makes it hard to understand the current
functionality. So simplify this internal API to match its use, we can
always change it in the future if it gets a different use-case.

1. CACBZZX5OQc45fUyDVayE89rkT=[email-masked]
   (https://public-inbox.org/git/CACBZZX5OQc45fUyDVayE89rkT=[email-masked]/)

Signed-off-by: Ævar Arnfjörð Bjarmason <[email-masked]>
---

On Fri, Jun 23 2017, Jeff King jotted:

> On Fri, Jun 23, 2017 at 04:36:06PM +0000, Ævar Arnfjörð Bjarmason wrote:
>
>> I believe this addresses the comments in the thread so far. Also Re:
>> René's "why const?" in [email-masked]:
>> Because tzname_from_tz isn't changed in the body of the function, only
>> read.
>
> Sure, it's not wrong. But that property is also held by 99% of the
> parameters that are passed by value. It's the normal style in our code
> base (and in most C code bases I know of) to never declare pass-by-value
> as const. It pollutes the interface and isn't something the caller cares
> about.
>
> Without passing judgement on whether that style is good or not (though
> IMHO it is), making this one case different than all the others is a bad
> idea. It makes the reader wonder why it's different.

Makes sense. I wasn't trying to be snary or curt or whatever. I'd just
never noticed this pattern in the codebase.

Seems a bit odd to me to not make use of the compiler guarding against
accidental assignments and giving it a strong hint to inline the value
where possible, but whatever, makes sense to have it stylistically be
consistent. So this version does that.

>> diff --git a/date.c b/date.c
>> index 1fd6d66375..17db07d905 100644
>> --- a/date.c
>> +++ b/date.c
>> @@ -256,7 +256,7 @@ const char *show_date(timestamp_t time, int tz, const struct date_mode *mode)
>>  			tm->tm_hour, tm->tm_min, tm->tm_sec, tz);
>>  	else if (mode->type == DATE_STRFTIME)
>>  		strbuf_addftime(&timebuf, mode->strftime_fmt, tm, tz,
>> -				mode->local ? NULL : "");
>> +				mode->local);
>
> You flipped the boolean here. That's OK by me. But in the definition...
>
>>  void strbuf_addftime(struct strbuf *sb, const char *fmt, const struct tm *tm,
>> -		     int tz_offset, const char *tz_name)
>> +		     int tz_offset, const int tzname_from_tz)
>
> Wouldn't tzname_from_tz only happen when we're _not_ in local mode? I
> suggested that name anticipating your second patch to actually compute
> it based on "tz". In local-mode it's not coming from tz, it's coming
> from secret unportable magic (the combination of localtime() and
> strftime()).

I misread (I think) an earlier E-Mail of yours and thought this was
what you were suggesting. This version hopefully looks OK.

>> @@ -815,8 +815,7 @@ void strbuf_addftime(struct strbuf *sb, const char *fmt, const struct tm *tm,
>>  			fmt++;
>>  			break;
>>  		case 'Z':
>> -			if (tz_name) {
>> -				strbuf_addstr(&munged_fmt, tz_name);
>> +			if (!tzname_from_tz) {
>>  				fmt++;
>>  				break;
>>  			}
>
> This logic matches your inversion in the caller, so it does the right
> thing. But I think the name is wrong, as above.

Fixed.

>> index 4559035c47..eba5d59a77 100644
>> --- a/strbuf.h
>> +++ b/strbuf.h
>> @@ -340,14 +340,15 @@ extern void strbuf_vaddf(struct strbuf *sb, const char *fmt, va_list ap);
>>  
>>  /**
>>   * Add the time specified by `tm`, as formatted by `strftime`.
>> - * `tz_name` is used to expand %Z internally unless it's NULL.
>>   * `tz_offset` is in decimal hhmm format, e.g. -600 means six hours west
>>   * of Greenwich, and it's used to expand %z internally.  However, tokens
>>   * with modifiers (e.g. %Ez) are passed to `strftime`.
>> + * `tzname_from_tz` when set, means let `strftime` format %Z, instead
>> + * of intercepting it and doing our own formatting.
>>   */
>>  extern void strbuf_addftime(struct strbuf *sb, const char *fmt,
>>  			    const struct tm *tm, int tz_offset,
>> -			    const char *tz_name);
>> +			    const int omit_strftime_tz_name);
>
> This would need the new name, too (whatever it is).

*Nod*. Now the parameter is called suppress_tz_name.

 date.c   | 2 +-
 strbuf.c | 5 ++---
 strbuf.h | 5 +++--
 3 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/date.c b/date.c
index 1fd6d66375..c3e673fd04 100644
--- a/date.c
+++ b/date.c
@@ -256,7 +256,7 @@ const char *show_date(timestamp_t time, int tz, const struct date_mode *mode)
 			tm->tm_hour, tm->tm_min, tm->tm_sec, tz);
 	else if (mode->type == DATE_STRFTIME)
 		strbuf_addftime(&timebuf, mode->strftime_fmt, tm, tz,
-				mode->local ? NULL : "");
+				!mode->local);
 	else
 		strbuf_addf(&timebuf, "%.3s %.3s %d %02d:%02d:%02d %d%c%+05d",
 				weekday_names[tm->tm_wday],
diff --git a/strbuf.c b/strbuf.c
index be3b9e37b1..89e40bb496 100644
--- a/strbuf.c
+++ b/strbuf.c
@@ -786,7 +786,7 @@ char *xstrfmt(const char *fmt, ...)
 }
 
 void strbuf_addftime(struct strbuf *sb, const char *fmt, const struct tm *tm,
-		     int tz_offset, const char *tz_name)
+		     int tz_offset, int suppress_tz_name)
 {
 	struct strbuf munged_fmt = STRBUF_INIT;
 	size_t hint = 128;
@@ -815,8 +815,7 @@ void strbuf_addftime(struct strbuf *sb, const char *fmt, const struct tm *tm,
 			fmt++;
 			break;
 		case 'Z':
-			if (tz_name) {
-				strbuf_addstr(&munged_fmt, tz_name);
+			if (suppress_tz_name) {
 				fmt++;
 				break;
 			}
diff --git a/strbuf.h b/strbuf.h
index 6708cef0f9..d3e6e65123 100644
--- a/strbuf.h
+++ b/strbuf.h
@@ -343,11 +343,12 @@ extern void strbuf_vaddf(struct strbuf *sb, const char *fmt, va_list ap);
  * `tz_offset` is in decimal hhmm format, e.g. -600 means six hours west
  * of Greenwich, and it's used to expand %z internally.  However, tokens
  * with modifiers (e.g. %Ez) are passed to `strftime`.
- * `tz_name` is used to expand %Z internally unless it's NULL.
+ * `suppress_tz_name` when set, means let suppress the `strftime` %Z
+ * format and replace it with an empty string.
  */
 extern void strbuf_addftime(struct strbuf *sb, const char *fmt,
 			    const struct tm *tm, int tz_offset,
-			    const char *tz_name);
+			    int suppress_tz_name);
 
 /**
  * Read a given size of data from a FILE* pointer to the buffer.
-- 
2.13.1.611.g7e3b11ae1