strbuf: provide CRLF-aware helper to read until a specified delimiter

Many of our commands support reading input that is separated either via
newlines or via NUL characters. Furthermore, in order to be a better
cross platform citizen, these commands typically know to strip the CRLF
sequence so that we also support reading newline-separated inputs on
e.g. the Windows platform. This results in the following kind of awkward
pattern:

```
struct strbuf input = STRBUF_INIT;

while (1) {
	int ret;

	if (nul_terminated)
		ret = strbuf_getline_nul(&input, stdin);
	else
		ret = strbuf_getline(&input, stdin);
	if (ret)
		break;

	...
}
```

Introduce a new CRLF-aware helper function that can read up to a user
specified delimiter. If the delimiter is `\n` the function knows to also
strip CRLF, otherwise it will only strip the specified delimiter. This
results in the following, much more readable code pattern:

```
struct strbuf input = STRBUF_INIT;

while (strbuf_getdelim_strip_crlf(&input, stdin, delim) != EOF) {
	...
}
```

The new function will be used in a subsequent commit.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
Patrick Steinhardt 2023-06-06 07:19:37 +02:00 коммит произвёл Junio C Hamano
Родитель b116c77307
Коммит af35e56b0f
2 изменённых файлов: 20 добавлений и 3 удалений

Просмотреть файл

@ -721,11 +721,11 @@ static int strbuf_getdelim(struct strbuf *sb, FILE *fp, int term)
return 0;
}
int strbuf_getline(struct strbuf *sb, FILE *fp)
int strbuf_getdelim_strip_crlf(struct strbuf *sb, FILE *fp, int term)
{
if (strbuf_getwholeline(sb, fp, '\n'))
if (strbuf_getwholeline(sb, fp, term))
return EOF;
if (sb->buf[sb->len - 1] == '\n') {
if (term == '\n' && sb->buf[sb->len - 1] == '\n') {
strbuf_setlen(sb, sb->len - 1);
if (sb->len && sb->buf[sb->len - 1] == '\r')
strbuf_setlen(sb, sb->len - 1);
@ -733,6 +733,11 @@ int strbuf_getline(struct strbuf *sb, FILE *fp)
return 0;
}
int strbuf_getline(struct strbuf *sb, FILE *fp)
{
return strbuf_getdelim_strip_crlf(sb, fp, '\n');
}
int strbuf_getline_lf(struct strbuf *sb, FILE *fp)
{
return strbuf_getdelim(sb, fp, '\n');

Просмотреть файл

@ -475,6 +475,18 @@ int strbuf_readlink(struct strbuf *sb, const char *path, size_t hint);
*/
ssize_t strbuf_write(struct strbuf *sb, FILE *stream);
/**
* Read from a FILE * until the specified terminator is encountered,
* overwriting the existing contents of the strbuf.
*
* Reading stops after the terminator or at EOF. The terminator is
* removed from the buffer before returning. If the terminator is LF
* and if it is preceded by a CR, then the whole CRLF is stripped.
* Returns 0 unless there was nothing left before EOF, in which case
* it returns `EOF`.
*/
int strbuf_getdelim_strip_crlf(struct strbuf *sb, FILE *fp, int term);
/**
* Read a line from a FILE *, overwriting the existing contents of
* the strbuf. The strbuf_getline*() family of functions share