LCOV - differential code coverage report
Current view: top level - src/common - pg_get_line.c (source / functions) Coverage Total Hit UBC GBC CBC
Current: Differential Code Coverage 16@8cea358b128 vs 17@8cea358b128 Lines: 77.1 % 35 27 8 1 26
Current Date: 2024-04-14 14:21:10 Functions: 100.0 % 3 3 3
Baseline: 16@8cea358b128 Branches: 80.0 % 20 16 4 1 15
Baseline Date: 2024-04-14 14:21:09 Line coverage date bins:
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed (240..) days: 77.1 % 35 27 8 1 26
Function coverage date bins:
(240..) days: 100.0 % 3 3 3
Branch coverage date bins:
(240..) days: 80.0 % 20 16 4 1 15

 Age         Owner                    Branch data    TLA  Line data    Source code
                                  1                 :                : /*-------------------------------------------------------------------------
                                  2                 :                :  *
                                  3                 :                :  * pg_get_line.c
                                  4                 :                :  *    fgets() with an expansible result buffer
                                  5                 :                :  *
                                  6                 :                :  * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group
                                  7                 :                :  * Portions Copyright (c) 1994, Regents of the University of California
                                  8                 :                :  *
                                  9                 :                :  *
                                 10                 :                :  * IDENTIFICATION
                                 11                 :                :  *    src/common/pg_get_line.c
                                 12                 :                :  *
                                 13                 :                :  *-------------------------------------------------------------------------
                                 14                 :                :  */
                                 15                 :                : #ifndef FRONTEND
                                 16                 :                : #include "postgres.h"
                                 17                 :                : #else
                                 18                 :                : #include "postgres_fe.h"
                                 19                 :                : #endif
                                 20                 :                : 
                                 21                 :                : #include <setjmp.h>
                                 22                 :                : 
                                 23                 :                : #include "common/string.h"
                                 24                 :                : #include "lib/stringinfo.h"
                                 25                 :                : 
                                 26                 :                : 
                                 27                 :                : /*
                                 28                 :                :  * pg_get_line()
                                 29                 :                :  *
                                 30                 :                :  * This is meant to be equivalent to fgets(), except that instead of
                                 31                 :                :  * reading into a caller-supplied, fixed-size buffer, it reads into
                                 32                 :                :  * a palloc'd (in frontend, really malloc'd) string, which is resized
                                 33                 :                :  * as needed to handle indefinitely long input lines.  The caller is
                                 34                 :                :  * responsible for pfree'ing the result string when appropriate.
                                 35                 :                :  *
                                 36                 :                :  * As with fgets(), returns NULL if there is a read error or if no
                                 37                 :                :  * characters are available before EOF.  The caller can distinguish
                                 38                 :                :  * these cases by checking ferror(stream).
                                 39                 :                :  *
                                 40                 :                :  * Since this is meant to be equivalent to fgets(), the trailing newline
                                 41                 :                :  * (if any) is not stripped.  Callers may wish to apply pg_strip_crlf().
                                 42                 :                :  *
                                 43                 :                :  * Note that while I/O errors are reflected back to the caller to be
                                 44                 :                :  * dealt with, an OOM condition for the palloc'd buffer will not be;
                                 45                 :                :  * there'll be an ereport(ERROR) or exit(1) inside stringinfo.c.
                                 46                 :                :  *
                                 47                 :                :  * Also note that the palloc'd buffer is usually a lot longer than
                                 48                 :                :  * strictly necessary, so it may be inadvisable to use this function
                                 49                 :                :  * to collect lots of long-lived data.  A less memory-hungry option
                                 50                 :                :  * is to use pg_get_line_buf() or pg_get_line_append() in a loop,
                                 51                 :                :  * then pstrdup() each line.
                                 52                 :                :  *
                                 53                 :                :  * prompt_ctx can optionally be provided to allow this function to be
                                 54                 :                :  * canceled via an existing SIGINT signal handler that will longjmp to the
                                 55                 :                :  * specified place only when *(prompt_ctx->enabled) is true.  If canceled,
                                 56                 :                :  * this function returns NULL, and prompt_ctx->canceled is set to true.
                                 57                 :                :  */
                                 58                 :                : char *
  879 tgl@sss.pgh.pa.us          59                 :CBC         895 : pg_get_line(FILE *stream, PromptInterruptContext *prompt_ctx)
                                 60                 :                : {
                                 61                 :                :     StringInfoData buf;
                                 62                 :                : 
 1319                            63                 :            895 :     initStringInfo(&buf);
                                 64                 :                : 
  879                            65         [ -  + ]:            895 :     if (!pg_get_line_append(stream, &buf, prompt_ctx))
                                 66                 :                :     {
                                 67                 :                :         /* ensure that free() doesn't mess up errno */
 1319 tgl@sss.pgh.pa.us          68                 :UBC           0 :         int         save_errno = errno;
                                 69                 :                : 
                                 70                 :              0 :         pfree(buf.data);
                                 71                 :              0 :         errno = save_errno;
                                 72                 :              0 :         return NULL;
                                 73                 :                :     }
                                 74                 :                : 
 1316 tgl@sss.pgh.pa.us          75                 :CBC         895 :     return buf.data;
                                 76                 :                : }
                                 77                 :                : 
                                 78                 :                : /*
                                 79                 :                :  * pg_get_line_buf()
                                 80                 :                :  *
                                 81                 :                :  * This has similar behavior to pg_get_line(), and thence to fgets(),
                                 82                 :                :  * except that the collected data is returned in a caller-supplied
                                 83                 :                :  * StringInfo buffer.  This is a convenient API for code that just
                                 84                 :                :  * wants to read and process one line at a time, without any artificial
                                 85                 :                :  * limit on line length.
                                 86                 :                :  *
                                 87                 :                :  * Returns true if a line was successfully collected (including the
                                 88                 :                :  * case of a non-newline-terminated line at EOF).  Returns false if
                                 89                 :                :  * there was an I/O error or no data was available before EOF.
                                 90                 :                :  * (Check ferror(stream) to distinguish these cases.)
                                 91                 :                :  *
                                 92                 :                :  * In the false-result case, buf is reset to empty.
                                 93                 :                :  */
                                 94                 :                : bool
 1300                            95                 :         801511 : pg_get_line_buf(FILE *stream, StringInfo buf)
                                 96                 :                : {
                                 97                 :                :     /* We just need to drop any data from the previous call */
                                 98                 :         801511 :     resetStringInfo(buf);
  879                            99                 :         801511 :     return pg_get_line_append(stream, buf, NULL);
                                100                 :                : }
                                101                 :                : 
                                102                 :                : /*
                                103                 :                :  * pg_get_line_append()
                                104                 :                :  *
                                105                 :                :  * This has similar behavior to pg_get_line(), and thence to fgets(),
                                106                 :                :  * except that the collected data is appended to whatever is in *buf.
                                107                 :                :  * This is useful in preference to pg_get_line_buf() if the caller wants
                                108                 :                :  * to merge some lines together, e.g. to implement backslash continuation.
                                109                 :                :  *
                                110                 :                :  * Returns true if a line was successfully collected (including the
                                111                 :                :  * case of a non-newline-terminated line at EOF).  Returns false if
                                112                 :                :  * there was an I/O error or no data was available before EOF.
                                113                 :                :  * (Check ferror(stream) to distinguish these cases.)
                                114                 :                :  *
                                115                 :                :  * In the false-result case, the contents of *buf are logically unmodified,
                                116                 :                :  * though it's possible that the buffer has been resized.
                                117                 :                :  *
                                118                 :                :  * prompt_ctx can optionally be provided to allow this function to be
                                119                 :                :  * canceled via an existing SIGINT signal handler that will longjmp to the
                                120                 :                :  * specified place only when *(prompt_ctx->enabled) is true.  If canceled,
                                121                 :                :  * this function returns false, and prompt_ctx->canceled is set to true.
                                122                 :                :  */
                                123                 :                : bool
                                124                 :         961268 : pg_get_line_append(FILE *stream, StringInfo buf,
                                125                 :                :                    PromptInterruptContext *prompt_ctx)
                                126                 :                : {
 1316                           127                 :         961268 :     int         orig_len = buf->len;
                                128                 :                : 
  879                           129   [ +  +  +  - ]:         961268 :     if (prompt_ctx && sigsetjmp(*((sigjmp_buf *) prompt_ctx->jmpbuf), 1) != 0)
                                130                 :                :     {
                                131                 :                :         /* Got here with longjmp */
  879 tgl@sss.pgh.pa.us         132                 :UBC           0 :         prompt_ctx->canceled = true;
                                133                 :                :         /* Discard any data we collected before detecting error */
                                134                 :              0 :         buf->len = orig_len;
                                135                 :              0 :         buf->data[orig_len] = '\0';
                                136                 :              0 :         return false;
                                137                 :                :     }
                                138                 :                : 
                                139                 :                :     /* Loop until newline or EOF/error */
                                140                 :                :     for (;;)
  879 tgl@sss.pgh.pa.us         141                 :CBC          20 :     {
                                142                 :                :         char       *res;
                                143                 :                : 
                                144                 :                :         /* Enable longjmp while waiting for input */
                                145         [ +  + ]:         961288 :         if (prompt_ctx)
                                146                 :              2 :             *(prompt_ctx->enabled) = true;
                                147                 :                : 
                                148                 :                :         /* Read some data, appending it to whatever we already have */
                                149                 :         961288 :         res = fgets(buf->data + buf->len, buf->maxlen - buf->len, stream);
                                150                 :                : 
                                151                 :                :         /* Disable longjmp again, then break if fgets failed */
                                152         [ +  + ]:         961288 :         if (prompt_ctx)
                                153                 :              2 :             *(prompt_ctx->enabled) = false;
                                154                 :                : 
                                155         [ +  + ]:         961288 :         if (res == NULL)
                                156                 :           2513 :             break;
                                157                 :                : 
                                158                 :                :         /* Got data, so update buf->len */
 1316                           159                 :         958775 :         buf->len += strlen(buf->data + buf->len);
                                160                 :                : 
                                161                 :                :         /* Done if we have collected a newline */
                                162   [ +  -  +  + ]:         958775 :         if (buf->len > orig_len && buf->data[buf->len - 1] == '\n')
                                163                 :         958755 :             return true;
                                164                 :                : 
                                165                 :                :         /* Make some more room in the buffer, and loop to read more data */
                                166                 :             20 :         enlargeStringInfo(buf, 128);
                                167                 :                :     }
                                168                 :                : 
                                169                 :                :     /* Check for I/O errors and EOF */
                                170   [ +  -  +  + ]:           2513 :     if (ferror(stream) || buf->len == orig_len)
                                171                 :                :     {
                                172                 :                :         /* Discard any data we collected before detecting error */
                                173                 :           2494 :         buf->len = orig_len;
                                174                 :           2494 :         buf->data[orig_len] = '\0';
                                175                 :           2494 :         return false;
                                176                 :                :     }
                                177                 :                : 
                                178                 :                :     /* No newline at EOF, but we did collect some data */
 1316 tgl@sss.pgh.pa.us         179                 :GBC          19 :     return true;
                                180                 :                : }
        

Generated by: LCOV version 2.1-beta2-3-g6141622