Skip to content

Commit 9314870

Browse files
committed
Rethink API for pg_get_line.c, one more time.
Further experience says that the appending behavior offered by pg_get_line_append is useful to only a very small minority of callers. For most, the requirement to reset the buffer after each line is just an error-prone nuisance. Hence, invent another alternative call pg_get_line_buf, which takes care of that detail. Noted while reviewing a patch from Daniel Gustafsson. Discussion: https://postgr.es/m/48A4FA71-524E-41B9-953A-FD04EF36E2E7@yesql.se
1 parent c4133ec commit 9314870

File tree

5 files changed

+32
-8
lines changed

5 files changed

+32
-8
lines changed

src/bin/initdb/initdb.c

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -486,7 +486,7 @@ readfile(const char *path)
486486
result = (char **) pg_malloc(maxlines * sizeof(char *));
487487

488488
n = 0;
489-
while (pg_get_line_append(infile, &line))
489+
while (pg_get_line_buf(infile, &line))
490490
{
491491
/* make sure there will be room for a trailing NULL pointer */
492492
if (n >= maxlines - 1)
@@ -496,8 +496,6 @@ readfile(const char *path)
496496
}
497497

498498
result[n++] = pg_strdup(line.data);
499-
500-
resetStringInfo(&line);
501499
}
502500
result[n] = NULL;
503501

src/common/pg_get_line.c

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,8 @@
4545
* Also note that the palloc'd buffer is usually a lot longer than
4646
* strictly necessary, so it may be inadvisable to use this function
4747
* to collect lots of long-lived data. A less memory-hungry option
48-
* is to use pg_get_line_append() in a loop, then pstrdup() each line.
48+
* is to use pg_get_line_buf() or pg_get_line_append() in a loop,
49+
* then pstrdup() each line.
4950
*/
5051
char *
5152
pg_get_line(FILE *stream)
@@ -67,11 +68,37 @@ pg_get_line(FILE *stream)
6768
return buf.data;
6869
}
6970

71+
/*
72+
* pg_get_line_buf()
73+
*
74+
* This has similar behavior to pg_get_line(), and thence to fgets(),
75+
* except that the collected data is returned in a caller-supplied
76+
* StringInfo buffer. This is a convenient API for code that just
77+
* wants to read and process one line at a time, without any artificial
78+
* limit on line length.
79+
*
80+
* Returns true if a line was successfully collected (including the
81+
* case of a non-newline-terminated line at EOF). Returns false if
82+
* there was an I/O error or no data was available before EOF.
83+
* (Check ferror(stream) to distinguish these cases.)
84+
*
85+
* In the false-result case, buf is reset to empty.
86+
*/
87+
bool
88+
pg_get_line_buf(FILE *stream, StringInfo buf)
89+
{
90+
/* We just need to drop any data from the previous call */
91+
resetStringInfo(buf);
92+
return pg_get_line_append(stream, buf);
93+
}
94+
7095
/*
7196
* pg_get_line_append()
7297
*
7398
* This has similar behavior to pg_get_line(), and thence to fgets(),
7499
* except that the collected data is appended to whatever is in *buf.
100+
* This is useful in preference to pg_get_line_buf() if the caller wants
101+
* to merge some lines together, e.g. to implement backslash continuation.
75102
*
76103
* Returns true if a line was successfully collected (including the
77104
* case of a non-newline-terminated line at EOF). Returns false if

src/include/common/string.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ extern int pg_strip_crlf(char *str);
2121

2222
/* functions in src/common/pg_get_line.c */
2323
extern char *pg_get_line(FILE *stream);
24+
extern bool pg_get_line_buf(FILE *stream, struct StringInfoData *buf);
2425
extern bool pg_get_line_append(FILE *stream, struct StringInfoData *buf);
2526

2627
/* functions in src/common/sprompt.c */

src/interfaces/ecpg/test/pg_regress_ecpg.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ ecpg_filter(const char *sourcefile, const char *outfile)
4949

5050
initStringInfo(&linebuf);
5151

52-
while (pg_get_line_append(s, &linebuf))
52+
while (pg_get_line_buf(s, &linebuf))
5353
{
5454
/* check for "#line " in the beginning */
5555
if (strstr(linebuf.data, "#line ") == linebuf.data)
@@ -69,7 +69,6 @@ ecpg_filter(const char *sourcefile, const char *outfile)
6969
}
7070
}
7171
fputs(linebuf.data, t);
72-
resetStringInfo(&linebuf);
7372
}
7473

7574
pfree(linebuf.data);

src/test/regress/pg_regress.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -566,15 +566,14 @@ convert_sourcefiles_in(const char *source_subdir, const char *dest_dir, const ch
566566

567567
initStringInfo(&line);
568568

569-
while (pg_get_line_append(infile, &line))
569+
while (pg_get_line_buf(infile, &line))
570570
{
571571
replace_string(&line, "@abs_srcdir@", inputdir);
572572
replace_string(&line, "@abs_builddir@", outputdir);
573573
replace_string(&line, "@testtablespace@", testtablespace);
574574
replace_string(&line, "@libdir@", dlpath);
575575
replace_string(&line, "@DLSUFFIX@", DLSUFFIX);
576576
fputs(line.data, outfile);
577-
resetStringInfo(&line);
578577
}
579578

580579
pfree(line.data);

0 commit comments

Comments
 (0)