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)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy