for-each-ref: refactor subject and body placeholder parsing

The find_subpos function was a little hard to use, as well as to read. It would sometimes write into the subject and body pointers, and sometimes not. The body pointer sometimes could be compared to subject, and sometimes not. When actually duplicating the subject, the caller was forced to figure out again how long the subject is (which is not too big a deal when the subject is a single line, but hard to extend). The refactoring makes the function more straightforward, both to read and to use. We will always put something into the subject and body pointers, and we return explicit lengths for them, too. This lays the groundwork both for more complex subject parsing (e.g., multiline), as well as splitting the body into subparts (like the text versus the signature). Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Jeff King committed Sep 7, 2011 at 13:44 UTC 7ec0f31eec66b854a2ca856538723dea5f1c0ab7
1 file changed +29 -25
builtin/for-each-ref.c
+29 -25
@@ -458,38 +458,42 @@ static void grab_person(const char *who, struct atom_value *val, int deref, stru
458 }
459 }
460
461 -static void find_subpos(const char *buf, unsigned long sz, const char **sub, const char **body)
461 +static void find_subpos(const char *buf, unsigned long sz,
462 + const char **sub, unsigned long *sublen,
463 + const char **body, unsigned long *bodylen)
464 {
463 - while (*buf) {
464 - const char *eol = strchr(buf, '\n');
465 - if (!eol)
466 - return;
467 - if (eol[1] == '\n') {
468 - buf = eol + 1;
469 - break; /* found end of header */
470 - }
471 - buf = eol + 1;
465 + const char *eol;
466 + /* skip past header until we hit empty line */
467 + while (*buf && *buf != '\n') {
468 + eol = strchrnul(buf, '\n');
469 + if (*eol)
470 + eol++;
471 + buf = eol;
472 }
473 + /* skip any empty lines */
474 while (*buf == '\n')
475 buf++;
475 - if (!*buf)
476 - return;
477 - *sub = buf; /* first non-empty line */
478 - buf = strchr(buf, '\n');
479 - if (!buf) {
480 - *body = "";
481 - return; /* no body */
482 - }
476 +
477 + /* subject is first non-empty line */
478 + *sub = buf;
479 + /* subject goes to end of line */
480 + eol = strchrnul(buf, '\n');
481 + *sublen = eol - buf;
482 + buf = eol;
483 +
484 + /* skip any empty lines */
485 while (*buf == '\n')
484 - buf++; /* skip blank between subject and body */
486 + buf++;
487 *body = buf;
488 + *bodylen = strlen(buf);
489 }
490
491 /* See grab_values */
492 static void grab_sub_body_contents(struct atom_value *val, int deref, struct object *obj, void *buf, unsigned long sz)
493 {
494 int i;
492 - const char *subpos = NULL, *bodypos = NULL;
495 + const char *subpos = NULL, *bodypos;
496 + unsigned long sublen, bodylen;
497
498 for (i = 0; i < used_atom_cnt; i++) {
499 const char *name = used_atom[i];
@@ -503,14 +507,14 @@ static void grab_sub_body_contents(struct atom_value *val, int deref, struct obj
507 strcmp(name, "contents"))
508 continue;
509 if (!subpos)
506 - find_subpos(buf, sz, &subpos, &bodypos);
507 - if (!subpos)
508 - return;
510 + find_subpos(buf, sz,
511 + &subpos, &sublen,
512 + &bodypos, &bodylen);
513
514 if (!strcmp(name, "subject"))
511 - v->s = copy_line(subpos);
515 + v->s = xmemdupz(subpos, sublen);
516 else if (!strcmp(name, "body"))
513 - v->s = xstrdup(bodypos);
517 + v->s = xmemdupz(bodypos, bodylen);
518 else if (!strcmp(name, "contents"))
519 v->s = xstrdup(subpos);
520 }