@matheusbsbs / matheus-bagliano / commits / c3a670de50
Fork 0

Avoid a useless prefix lookup in strbuf_expand()

Currently, the --pretty=format prefix is looked up in a tight loop in strbuf_expand(), if prefix is found it is then used as argument for format_commit_item() that does another search by a switch statement to select the proper operation. Because the switch statement is already able to discard unknown matches we don't need the prefix lookup before to call format_commit_item(). Signed-off-by: Marco Costalba <mcostalba@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Marco Costalba committed Feb 9, 2008 at 15:40 UTC c3a670de50589dedf2d9b83305e8bd0ff63a1a60
3 files changed +83 -108
pretty.c
+73 -95
@@ -282,59 +282,59 @@ static char *logmsg_reencode(const struct commit *commit,
282 return out;
283 }
284
285 -static void format_person_part(struct strbuf *sb, char part,
285 +static size_t format_person_part(struct strbuf *sb, char part,
286 const char *msg, int len)
287 {
288 + /* currently all placeholders have same length */
289 + const int placeholder_len = 2;
290 int start, end, tz = 0;
289 - unsigned long date;
291 + unsigned long date = 0;
292 char *ep;
293
292 - /* parse name */
294 + /* advance 'end' to point to email start delimiter */
295 for (end = 0; end < len && msg[end] != '<'; end++)
296 ; /* do nothing */
297 +
298 /*
296 - * If it does not even have a '<' and '>', that is
297 - * quite a bogus commit author and we discard it;
298 - * this is in line with add_user_info() that is used
299 - * in the normal codepath. When end points at the '<'
300 - * that we found, it should have matching '>' later,
301 - * which means start (beginning of email address) must
302 - * be strictly below len.
299 + * When end points at the '<' that we found, it should have
300 + * matching '>' later, which means 'end' must be strictly
301 + * below len - 1.
302 */
304 - start = end + 1;
305 - if (start >= len - 1)
306 - return;
307 - while (end > 0 && isspace(msg[end - 1]))
308 - end--;
303 + if (end >= len - 2)
304 + goto skip;
305 +
306 if (part == 'n') { /* name */
307 + while (end > 0 && isspace(msg[end - 1]))
308 + end--;
309 strbuf_add(sb, msg, end);
311 - return;
310 + return placeholder_len;
311 }
312 + start = ++end; /* save email start position */
313
314 - /* parse email */
315 - for (end = start; end < len && msg[end] != '>'; end++)
314 + /* advance 'end' to point to email end delimiter */
315 + for ( ; end < len && msg[end] != '>'; end++)
316 ; /* do nothing */
317
318 if (end >= len)
319 - return;
319 + goto skip;
320
321 if (part == 'e') { /* email */
322 strbuf_add(sb, msg + start, end - start);
323 - return;
323 + return placeholder_len;
324 }
325
326 - /* parse date */
326 + /* advance 'start' to point to date start delimiter */
327 for (start = end + 1; start < len && isspace(msg[start]); start++)
328 ; /* do nothing */
329 if (start >= len)
330 - return;
330 + goto skip;
331 date = strtoul(msg + start, &ep, 10);
332 if (msg + start == ep)
333 - return;
333 + goto skip;
334
335 if (part == 't') { /* date, UNIX timestamp */
336 strbuf_add(sb, msg + start, ep - (msg + start));
337 - return;
337 + return placeholder_len;
338 }
339
340 /* parse tz */
@@ -349,17 +349,28 @@ static void format_person_part(struct strbuf *sb, char part,
349 switch (part) {
350 case 'd': /* date */
351 strbuf_addstr(sb, show_date(date, tz, DATE_NORMAL));
352 - return;
352 + return placeholder_len;
353 case 'D': /* date, RFC2822 style */
354 strbuf_addstr(sb, show_date(date, tz, DATE_RFC2822));
355 - return;
355 + return placeholder_len;
356 case 'r': /* date, relative */
357 strbuf_addstr(sb, show_date(date, tz, DATE_RELATIVE));
358 - return;
358 + return placeholder_len;
359 case 'i': /* date, ISO 8601 */
360 strbuf_addstr(sb, show_date(date, tz, DATE_ISO8601));
361 - return;
361 + return placeholder_len;
362 }
363 +
364 +skip:
365 + /*
366 + * bogus commit, 'sb' cannot be updated, but we still need to
367 + * compute a valid return value.
368 + */
369 + if (part == 'n' || part == 'e' || part == 't' || part == 'd'
370 + || part == 'D' || part == 'r' || part == 'i')
371 + return placeholder_len;
372 +
373 + return 0; /* unknown placeholder */
374 }
375
376 struct chunk {
@@ -440,7 +451,7 @@ static void parse_commit_header(struct format_commit_context *context)
451 context->commit_header_parsed = 1;
452 }
453
443 -static void format_commit_item(struct strbuf *sb, const char *placeholder,
454 +static size_t format_commit_item(struct strbuf *sb, const char *placeholder,
455 void *context)
456 {
457 struct format_commit_context *c = context;
@@ -451,23 +462,23 @@ static void format_commit_item(struct strbuf *sb, const char *placeholder,
462 /* these are independent of the commit */
463 switch (placeholder[0]) {
464 case 'C':
454 - switch (placeholder[3]) {
455 - case 'd': /* red */
465 + if (!prefixcmp(placeholder + 1, "red")) {
466 strbuf_addstr(sb, "\033[31m");
457 - return;
458 - case 'e': /* green */
467 + return 4;
468 + } else if (!prefixcmp(placeholder + 1, "green")) {
469 strbuf_addstr(sb, "\033[32m");
460 - return;
461 - case 'u': /* blue */
470 + return 6;
471 + } else if (!prefixcmp(placeholder + 1, "blue")) {
472 strbuf_addstr(sb, "\033[34m");
463 - return;
464 - case 's': /* reset color */
473 + return 5;
474 + } else if (!prefixcmp(placeholder + 1, "reset")) {
475 strbuf_addstr(sb, "\033[m");
466 - return;
467 - }
476 + return 6;
477 + } else
478 + return 0;
479 case 'n': /* newline */
480 strbuf_addch(sb, '\n');
470 - return;
481 + return 1;
482 }
483
484 /* these depend on the commit */
@@ -477,34 +488,34 @@ static void format_commit_item(struct strbuf *sb, const char *placeholder,
488 switch (placeholder[0]) {
489 case 'H': /* commit hash */
490 strbuf_addstr(sb, sha1_to_hex(commit->object.sha1));
480 - return;
491 + return 1;
492 case 'h': /* abbreviated commit hash */
493 if (add_again(sb, &c->abbrev_commit_hash))
483 - return;
494 + return 1;
495 strbuf_addstr(sb, find_unique_abbrev(commit->object.sha1,
496 DEFAULT_ABBREV));
497 c->abbrev_commit_hash.len = sb->len - c->abbrev_commit_hash.off;
487 - return;
498 + return 1;
499 case 'T': /* tree hash */
500 strbuf_addstr(sb, sha1_to_hex(commit->tree->object.sha1));
490 - return;
501 + return 1;
502 case 't': /* abbreviated tree hash */
503 if (add_again(sb, &c->abbrev_tree_hash))
493 - return;
504 + return 1;
505 strbuf_addstr(sb, find_unique_abbrev(commit->tree->object.sha1,
506 DEFAULT_ABBREV));
507 c->abbrev_tree_hash.len = sb->len - c->abbrev_tree_hash.off;
497 - return;
508 + return 1;
509 case 'P': /* parent hashes */
510 for (p = commit->parents; p; p = p->next) {
511 if (p != commit->parents)
512 strbuf_addch(sb, ' ');
513 strbuf_addstr(sb, sha1_to_hex(p->item->object.sha1));
514 }
504 - return;
515 + return 1;
516 case 'p': /* abbreviated parent hashes */
517 if (add_again(sb, &c->abbrev_parent_hashes))
507 - return;
518 + return 1;
519 for (p = commit->parents; p; p = p->next) {
520 if (p != commit->parents)
521 strbuf_addch(sb, ' ');
@@ -513,14 +524,14 @@ static void format_commit_item(struct strbuf *sb, const char *placeholder,
524 }
525 c->abbrev_parent_hashes.len = sb->len -
526 c->abbrev_parent_hashes.off;
516 - return;
527 + return 1;
528 case 'm': /* left/right/bottom */
529 strbuf_addch(sb, (commit->object.flags & BOUNDARY)
530 ? '-'
531 : (commit->object.flags & SYMMETRIC_LEFT)
532 ? '<'
533 : '>');
523 - return;
534 + return 1;
535 }
536
537 /* For the rest we have to parse the commit header. */
@@ -528,66 +539,33 @@ static void format_commit_item(struct strbuf *sb, const char *placeholder,
539 parse_commit_header(c);
540
541 switch (placeholder[0]) {
531 - case 's':
542 + case 's': /* subject */
543 strbuf_add(sb, msg + c->subject.off, c->subject.len);
533 - return;
534 - case 'a':
535 - format_person_part(sb, placeholder[1],
544 + return 1;
545 + case 'a': /* author ... */
546 + return format_person_part(sb, placeholder[1],
547 msg + c->author.off, c->author.len);
537 - return;
538 - case 'c':
539 - format_person_part(sb, placeholder[1],
548 + case 'c': /* committer ... */
549 + return format_person_part(sb, placeholder[1],
550 msg + c->committer.off, c->committer.len);
541 - return;
542 - case 'e':
551 + case 'e': /* encoding */
552 strbuf_add(sb, msg + c->encoding.off, c->encoding.len);
544 - return;
545 - case 'b':
553 + return 1;
554 + case 'b': /* body */
555 strbuf_addstr(sb, msg + c->body_off);
547 - return;
556 + return 1;
557 }
558 + return 0; /* unknown placeholder */
559 }
560
561 void format_commit_message(const struct commit *commit,
562 const void *format, struct strbuf *sb)
563 {
554 - const char *placeholders[] = {
555 - "H", /* commit hash */
556 - "h", /* abbreviated commit hash */
557 - "T", /* tree hash */
558 - "t", /* abbreviated tree hash */
559 - "P", /* parent hashes */
560 - "p", /* abbreviated parent hashes */
561 - "an", /* author name */
562 - "ae", /* author email */
563 - "ad", /* author date */
564 - "aD", /* author date, RFC2822 style */
565 - "ar", /* author date, relative */
566 - "at", /* author date, UNIX timestamp */
567 - "ai", /* author date, ISO 8601 */
568 - "cn", /* committer name */
569 - "ce", /* committer email */
570 - "cd", /* committer date */
571 - "cD", /* committer date, RFC2822 style */
572 - "cr", /* committer date, relative */
573 - "ct", /* committer date, UNIX timestamp */
574 - "ci", /* committer date, ISO 8601 */
575 - "e", /* encoding */
576 - "s", /* subject */
577 - "b", /* body */
578 - "Cred", /* red */
579 - "Cgreen", /* green */
580 - "Cblue", /* blue */
581 - "Creset", /* reset color */
582 - "n", /* newline */
583 - "m", /* left/right/bottom */
584 - NULL
585 - };
564 struct format_commit_context context;
565
566 memset(&context, 0, sizeof(context));
567 context.commit = commit;
590 - strbuf_expand(sb, format, placeholders, format_commit_item, &context);
568 + strbuf_expand(sb, format, format_commit_item, &context);
569 }
570
571 static void pp_header(enum cmit_fmt fmt,
strbuf.c
+8 -11
@@ -146,11 +146,12 @@ void strbuf_addf(struct strbuf *sb, const char *fmt, ...)
146 strbuf_setlen(sb, sb->len + len);
147 }
148
149 -void strbuf_expand(struct strbuf *sb, const char *format,
150 - const char **placeholders, expand_fn_t fn, void *context)
149 +void strbuf_expand(struct strbuf *sb, const char *format, expand_fn_t fn,
150 + void *context)
151 {
152 for (;;) {
153 - const char *percent, **p;
153 + const char *percent;
154 + size_t consumed;
155
156 percent = strchrnul(format, '%');
157 strbuf_add(sb, format, percent - format);
@@ -158,14 +159,10 @@ void strbuf_expand(struct strbuf *sb, const char *format,
159 break;
160 format = percent + 1;
161
161 - for (p = placeholders; *p; p++) {
162 - if (!prefixcmp(format, *p))
163 - break;
164 - }
165 - if (*p) {
166 - fn(sb, *p, context);
167 - format += strlen(*p);
168 - } else
162 + consumed = fn(sb, format, context);
163 + if (consumed)
164 + format += consumed;
165 + else
166 strbuf_addch(sb, '%');
167 }
168 }
strbuf.h
+2 -2
@@ -103,8 +103,8 @@ static inline void strbuf_addbuf(struct strbuf *sb, struct strbuf *sb2) {
103 }
104 extern void strbuf_adddup(struct strbuf *sb, size_t pos, size_t len);
105
106 -typedef void (*expand_fn_t) (struct strbuf *sb, const char *placeholder, void *context);
107 -extern void strbuf_expand(struct strbuf *sb, const char *format, const char **placeholders, expand_fn_t fn, void *context);
106 +typedef size_t (*expand_fn_t) (struct strbuf *sb, const char *placeholder, void *context);
107 +extern void strbuf_expand(struct strbuf *sb, const char *format, expand_fn_t fn, void *context);
108
109 __attribute__((format(printf,2,3)))
110 extern void strbuf_addf(struct strbuf *sb, const char *fmt, ...);