LCOV - differential code coverage report
Current view: top level - src/common - stringinfo.c (source / functions) Coverage Total Hit UNC UBC GNC CBC
Current: Differential Code Coverage 16@8cea358b128 vs 17@8cea358b128 Lines: 91.5 % 94 86 8 7 79
Current Date: 2024-04-14 14:21:10 Functions: 100.0 % 12 12 3 9
Baseline: 16@8cea358b128 Branches: 63.9 % 36 23 3 10 3 20
Baseline Date: 2024-04-14 14:21:09 Line coverage date bins:
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed [..60] days: 100.0 % 5 5 5
(120,180] days: 100.0 % 2 2 2
(240..) days: 90.8 % 87 79 8 79
Function coverage date bins:
[..60] days: 100.0 % 1 1 1
(240..) days: 100.0 % 11 11 2 9
Branch coverage date bins:
[..60] days: 50.0 % 2 1 1 1
(120,180] days: 50.0 % 4 2 2 2
(240..) days: 66.7 % 30 20 10 20

 Age         Owner                    Branch data    TLA  Line data    Source code
                                  1                 :                : /*-------------------------------------------------------------------------
                                  2                 :                :  *
                                  3                 :                :  * stringinfo.c
                                  4                 :                :  *
                                  5                 :                :  * StringInfo provides an extensible string data type (currently limited to a
                                  6                 :                :  * length of 1GB).  It can be used to buffer either ordinary C strings
                                  7                 :                :  * (null-terminated text) or arbitrary binary data.  All storage is allocated
                                  8                 :                :  * with palloc() (falling back to malloc in frontend code).
                                  9                 :                :  *
                                 10                 :                :  * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group
                                 11                 :                :  * Portions Copyright (c) 1994, Regents of the University of California
                                 12                 :                :  *
                                 13                 :                :  *    src/common/stringinfo.c
                                 14                 :                :  *
                                 15                 :                :  *-------------------------------------------------------------------------
                                 16                 :                :  */
                                 17                 :                : 
                                 18                 :                : #ifndef FRONTEND
                                 19                 :                : 
                                 20                 :                : #include "postgres.h"
                                 21                 :                : #include "utils/memutils.h"
                                 22                 :                : 
                                 23                 :                : #else
                                 24                 :                : 
                                 25                 :                : #include "postgres_fe.h"
                                 26                 :                : 
                                 27                 :                : /* It's possible we could use a different value for this in frontend code */
                                 28                 :                : #define MaxAllocSize    ((Size) 0x3fffffff) /* 1 gigabyte - 1 */
                                 29                 :                : 
                                 30                 :                : #endif
                                 31                 :                : 
                                 32                 :                : #include "lib/stringinfo.h"
                                 33                 :                : 
                                 34                 :                : 
                                 35                 :                : /*
                                 36                 :                :  * makeStringInfo
                                 37                 :                :  *
                                 38                 :                :  * Create an empty 'StringInfoData' & return a pointer to it.
                                 39                 :                :  */
                                 40                 :                : StringInfo
 9121 tgl@sss.pgh.pa.us          41                 :CBC       48868 : makeStringInfo(void)
                                 42                 :                : {
                                 43                 :                :     StringInfo  res;
                                 44                 :                : 
 9716 bruce@momjian.us           45                 :          48868 :     res = (StringInfo) palloc(sizeof(StringInfoData));
                                 46                 :                : 
 9121 tgl@sss.pgh.pa.us          47                 :          48868 :     initStringInfo(res);
                                 48                 :                : 
 9357 bruce@momjian.us           49                 :          48868 :     return res;
                                 50                 :                : }
                                 51                 :                : 
                                 52                 :                : /*
                                 53                 :                :  * initStringInfo
                                 54                 :                :  *
                                 55                 :                :  * Initialize a StringInfoData struct (with previously undefined contents)
                                 56                 :                :  * to describe an empty string.
                                 57                 :                :  */
                                 58                 :                : void
 9121 tgl@sss.pgh.pa.us          59                 :        4771173 : initStringInfo(StringInfo str)
                                 60                 :                : {
 5995 bruce@momjian.us           61                 :        4771173 :     int         size = 1024;    /* initial default buffer size */
                                 62                 :                : 
 8993 tgl@sss.pgh.pa.us          63                 :        4771173 :     str->data = (char *) palloc(size);
 9121                            64                 :        4771173 :     str->maxlen = size;
 6252 neilc@samurai.com          65                 :        4771173 :     resetStringInfo(str);
                                 66                 :        4771173 : }
                                 67                 :                : 
                                 68                 :                : /*
                                 69                 :                :  * resetStringInfo
                                 70                 :                :  *
                                 71                 :                :  * Reset the StringInfo: the data buffer remains valid, but its
                                 72                 :                :  * previous content, if any, is cleared.
                                 73                 :                :  *
                                 74                 :                :  * Read-only StringInfos as initialized by initReadOnlyStringInfo cannot be
                                 75                 :                :  * reset.
                                 76                 :                :  */
                                 77                 :                : void
                                 78                 :       16292531 : resetStringInfo(StringInfo str)
                                 79                 :                : {
                                 80                 :                :     /* don't allow resets of read-only StringInfos */
  171 drowley@postgresql.o       81         [ -  + ]:GNC    16292531 :     Assert(str->maxlen != 0);
                                 82                 :                : 
 9121 tgl@sss.pgh.pa.us          83                 :CBC    16292531 :     str->data[0] = '\0';
 6252 neilc@samurai.com          84                 :       16292531 :     str->len = 0;
 7666 tgl@sss.pgh.pa.us          85                 :       16292531 :     str->cursor = 0;
 9121                            86                 :       16292531 : }
                                 87                 :                : 
                                 88                 :                : /*
                                 89                 :                :  * appendStringInfo
                                 90                 :                :  *
                                 91                 :                :  * Format text data under the control of fmt (an sprintf-style format string)
                                 92                 :                :  * and append it to whatever is already in str.  More space is allocated
                                 93                 :                :  * to str if necessary.  This is sort of like a combination of sprintf and
                                 94                 :                :  * strcat.
                                 95                 :                :  */
                                 96                 :                : void
 7559 bruce@momjian.us           97                 :       12107644 : appendStringInfo(StringInfo str, const char *fmt,...)
                                 98                 :                : {
 2027 tgl@sss.pgh.pa.us          99                 :       12107644 :     int         save_errno = errno;
                                100                 :                : 
                                101                 :                :     for (;;)
 7661                           102                 :          18329 :     {
                                103                 :                :         va_list     args;
                                104                 :                :         int         needed;
                                105                 :                : 
                                106                 :                :         /* Try to format the data. */
 2027                           107                 :       12125973 :         errno = save_errno;
 7661                           108                 :       12125973 :         va_start(args, fmt);
 3825                           109                 :       12125973 :         needed = appendStringInfoVA(str, fmt, args);
 7661                           110                 :       12125973 :         va_end(args);
                                111                 :                : 
 3825                           112         [ +  + ]:       12125973 :         if (needed == 0)
                                113                 :       12107644 :             break;              /* success */
                                114                 :                : 
                                115                 :                :         /* Increase the buffer size and try again. */
                                116                 :          18329 :         enlargeStringInfo(str, needed);
                                117                 :                :     }
 7661                           118                 :       12107644 : }
                                119                 :                : 
                                120                 :                : /*
                                121                 :                :  * appendStringInfoVA
                                122                 :                :  *
                                123                 :                :  * Attempt to format text data under the control of fmt (an sprintf-style
                                124                 :                :  * format string) and append it to whatever is already in str.  If successful
                                125                 :                :  * return zero; if not (because there's not enough space), return an estimate
                                126                 :                :  * of the space needed, without modifying str.  Typically the caller should
                                127                 :                :  * pass the return value to enlargeStringInfo() before trying again; see
                                128                 :                :  * appendStringInfo for standard usage pattern.
                                129                 :                :  *
                                130                 :                :  * Caution: callers must be sure to preserve their entry-time errno
                                131                 :                :  * when looping, in case the fmt contains "%m".
                                132                 :                :  *
                                133                 :                :  * XXX This API is ugly, but there seems no alternative given the C spec's
                                134                 :                :  * restrictions on what can portably be done with va_list arguments: you have
                                135                 :                :  * to redo va_start before you can rescan the argument list, and we can't do
                                136                 :                :  * that from here.
                                137                 :                :  */
                                138                 :                : int
                                139                 :       12782773 : appendStringInfoVA(StringInfo str, const char *fmt, va_list args)
                                140                 :                : {
                                141                 :                :     int         avail;
                                142                 :                :     size_t      nprinted;
                                143                 :                : 
 9121                           144         [ -  + ]:       12782773 :     Assert(str != NULL);
                                145                 :                : 
                                146                 :                :     /*
                                147                 :                :      * If there's hardly any space, don't bother trying, just fail to make the
                                148                 :                :      * caller enlarge the buffer first.  We have to guess at how much to
                                149                 :                :      * enlarge, since we're skipping the formatting work.
                                150                 :                :      */
 3825                           151                 :       12782773 :     avail = str->maxlen - str->len;
 7661                           152         [ +  + ]:       12782773 :     if (avail < 16)
 3825                           153                 :          17293 :         return 32;
                                154                 :                : 
                                155                 :       12765480 :     nprinted = pvsnprintf(str->data + str->len, (size_t) avail, fmt, args);
                                156                 :                : 
                                157         [ +  + ]:       12765480 :     if (nprinted < (size_t) avail)
                                158                 :                :     {
                                159                 :                :         /* Success.  Note nprinted does not include trailing null. */
                                160                 :       12763052 :         str->len += (int) nprinted;
                                161                 :       12763052 :         return 0;
                                162                 :                :     }
                                163                 :                : 
                                164                 :                :     /* Restore the trailing null so that str is unmodified. */
 7661                           165                 :           2428 :     str->data[str->len] = '\0';
                                166                 :                : 
                                167                 :                :     /*
                                168                 :                :      * Return pvsnprintf's estimate of the space needed.  (Although this is
                                169                 :                :      * given as a size_t, we know it will fit in int because it's not more
                                170                 :                :      * than MaxAllocSize.)
                                171                 :                :      */
 3825                           172                 :           2428 :     return (int) nprinted;
                                173                 :                : }
                                174                 :                : 
                                175                 :                : /*
                                176                 :                :  * appendStringInfoString
                                177                 :                :  *
                                178                 :                :  * Append a null-terminated string to str.
                                179                 :                :  * Like appendStringInfo(str, "%s", s) but faster.
                                180                 :                :  */
                                181                 :                : void
 7661                           182                 :        7972253 : appendStringInfoString(StringInfo str, const char *s)
                                183                 :                : {
                                184                 :        7972253 :     appendBinaryStringInfo(str, s, strlen(s));
 9121                           185                 :        7972253 : }
                                186                 :                : 
                                187                 :                : /*
                                188                 :                :  * appendStringInfoChar
                                189                 :                :  *
                                190                 :                :  * Append a single byte to str.
                                191                 :                :  * Like appendStringInfo(str, "%c", ch) but much faster.
                                192                 :                :  */
                                193                 :                : void
                                194                 :       39456990 : appendStringInfoChar(StringInfo str, char ch)
                                195                 :                : {
                                196                 :                :     /* Make more room if needed */
 8931                           197         [ +  + ]:       39456990 :     if (str->len + 1 >= str->maxlen)
                                198                 :          11244 :         enlargeStringInfo(str, 1);
                                199                 :                : 
                                200                 :                :     /* OK, append the character */
 9121                           201                 :       39456990 :     str->data[str->len] = ch;
                                202                 :       39456990 :     str->len++;
                                203                 :       39456990 :     str->data[str->len] = '\0';
                                204                 :       39456990 : }
                                205                 :                : 
                                206                 :                : /*
                                207                 :                :  * appendStringInfoSpaces
                                208                 :                :  *
                                209                 :                :  * Append the specified number of spaces to a buffer.
                                210                 :                :  */
                                211                 :                : void
 5378                           212                 :          86211 : appendStringInfoSpaces(StringInfo str, int count)
                                213                 :                : {
                                214         [ +  + ]:          86211 :     if (count > 0)
                                215                 :                :     {
                                216                 :                :         /* Make more room if needed */
                                217                 :          83547 :         enlargeStringInfo(str, count);
                                218                 :                : 
                                219                 :                :         /* OK, append the spaces */
  450 drowley@postgresql.o      220                 :          83547 :         memset(&str->data[str->len], ' ', count);
                                221                 :          83547 :         str->len += count;
 5378 tgl@sss.pgh.pa.us         222                 :          83547 :         str->data[str->len] = '\0';
                                223                 :                :     }
                                224                 :          86211 : }
                                225                 :                : 
                                226                 :                : /*
                                227                 :                :  * appendBinaryStringInfo
                                228                 :                :  *
                                229                 :                :  * Append arbitrary binary data to a StringInfo, allocating more space
                                230                 :                :  * if necessary. Ensures that a trailing null byte is present.
                                231                 :                :  */
                                232                 :                : void
  471 peter@eisentraut.org      233                 :       16929717 : appendBinaryStringInfo(StringInfo str, const void *data, int datalen)
                                234                 :                : {
 9121 tgl@sss.pgh.pa.us         235         [ -  + ]:       16929717 :     Assert(str != NULL);
                                236                 :                : 
                                237                 :                :     /* Make more room if needed */
                                238                 :       16929717 :     enlargeStringInfo(str, datalen);
                                239                 :                : 
                                240                 :                :     /* OK, append the data */
                                241                 :       16929717 :     memcpy(str->data + str->len, data, datalen);
                                242                 :       16929717 :     str->len += datalen;
                                243                 :                : 
                                244                 :                :     /*
                                245                 :                :      * Keep a trailing null in place, even though it's probably useless for
                                246                 :                :      * binary data.  (Some callers are dealing with text but call this because
                                247                 :                :      * their input isn't null-terminated.)
                                248                 :                :      */
                                249                 :       16929717 :     str->data[str->len] = '\0';
10141 scrappy@hub.org           250                 :       16929717 : }
                                251                 :                : 
                                252                 :                : /*
                                253                 :                :  * appendBinaryStringInfoNT
                                254                 :                :  *
                                255                 :                :  * Append arbitrary binary data to a StringInfo, allocating more space
                                256                 :                :  * if necessary. Does not ensure a trailing null-byte exists.
                                257                 :                :  */
                                258                 :                : void
  471 peter@eisentraut.org      259                 :       14988591 : appendBinaryStringInfoNT(StringInfo str, const void *data, int datalen)
                                260                 :                : {
 2377 andres@anarazel.de        261         [ -  + ]:       14988591 :     Assert(str != NULL);
                                262                 :                : 
                                263                 :                :     /* Make more room if needed */
                                264                 :       14988591 :     enlargeStringInfo(str, datalen);
                                265                 :                : 
                                266                 :                :     /* OK, append the data */
                                267                 :       14988591 :     memcpy(str->data + str->len, data, datalen);
                                268                 :       14988591 :     str->len += datalen;
                                269                 :       14988591 : }
                                270                 :                : 
                                271                 :                : /*
                                272                 :                :  * enlargeStringInfo
                                273                 :                :  *
                                274                 :                :  * Make sure there is enough space for 'needed' more bytes
                                275                 :                :  * ('needed' does not include the terminating null).
                                276                 :                :  *
                                277                 :                :  * External callers usually need not concern themselves with this, since
                                278                 :                :  * all stringinfo.c routines do it automatically.  However, if a caller
                                279                 :                :  * knows that a StringInfo will eventually become X bytes large, it
                                280                 :                :  * can save some palloc overhead by enlarging the buffer before starting
                                281                 :                :  * to store data in it.
                                282                 :                :  *
                                283                 :                :  * NB: In the backend, because we use repalloc() to enlarge the buffer, the
                                284                 :                :  * string buffer will remain allocated in the same memory context that was
                                285                 :                :  * current when initStringInfo was called, even if another context is now
                                286                 :                :  * current.  This is the desired and indeed critical behavior!
                                287                 :                :  */
                                288                 :                : void
 7666 tgl@sss.pgh.pa.us         289                 :       56210815 : enlargeStringInfo(StringInfo str, int needed)
                                290                 :                : {
                                291                 :                :     int         newlen;
                                292                 :                : 
                                293                 :                :     /* validate this is not a read-only StringInfo */
  171 drowley@postgresql.o      294         [ -  + ]:GNC    56210815 :     Assert(str->maxlen != 0);
                                295                 :                : 
                                296                 :                :     /*
                                297                 :                :      * Guard against out-of-range "needed" values.  Without this, we can get
                                298                 :                :      * an overflow or infinite loop in the following.
                                299                 :                :      */
 6166 tgl@sss.pgh.pa.us         300         [ -  + ]:CBC    56210815 :     if (needed < 0)              /* should not happen */
                                301                 :                :     {
                                302                 :                : #ifndef FRONTEND
 6166 tgl@sss.pgh.pa.us         303         [ #  # ]:UBC           0 :         elog(ERROR, "invalid string enlargement request size: %d", needed);
                                304                 :                : #else
 1622 andres@anarazel.de        305                 :              0 :         fprintf(stderr, "invalid string enlargement request size: %d\n", needed);
                                306                 :              0 :         exit(EXIT_FAILURE);
                                307                 :                : #endif
                                308                 :                :     }
 2531 alvherre@alvh.no-ip.      309         [ -  + ]:CBC    56210815 :     if (((Size) needed) >= (MaxAllocSize - (Size) str->len))
                                310                 :                :     {
                                311                 :                : #ifndef FRONTEND
 6166 tgl@sss.pgh.pa.us         312         [ #  # ]:UBC           0 :         ereport(ERROR,
                                313                 :                :                 (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
                                314                 :                :                  errmsg("out of memory"),
                                315                 :                :                  errdetail("Cannot enlarge string buffer containing %d bytes by %d more bytes.",
                                316                 :                :                            str->len, needed)));
                                317                 :                : #else
 1622 andres@anarazel.de        318                 :              0 :         fprintf(stderr,
                                319                 :              0 :                 _("out of memory\n\nCannot enlarge string buffer containing %d bytes by %d more bytes.\n"),
                                320                 :                :                 str->len, needed);
                                321                 :              0 :         exit(EXIT_FAILURE);
                                322                 :                : #endif
                                323                 :                :     }
                                324                 :                : 
 7666 tgl@sss.pgh.pa.us         325                 :CBC    56210815 :     needed += str->len + 1;      /* total space required now */
                                326                 :                : 
                                327                 :                :     /* Because of the above test, we now have needed <= MaxAllocSize */
                                328                 :                : 
                                329         [ +  + ]:       56210815 :     if (needed <= str->maxlen)
                                330                 :       56117943 :         return;                 /* got enough space already */
                                331                 :                : 
                                332                 :                :     /*
                                333                 :                :      * We don't want to allocate just a little more space with each append;
                                334                 :                :      * for efficiency, double the buffer size each time it overflows.
                                335                 :                :      * Actually, we might need to more than double it if 'needed' is big...
                                336                 :                :      */
 2531 alvherre@alvh.no-ip.      337                 :          92872 :     newlen = 2 * str->maxlen;
                                338         [ +  + ]:         208996 :     while (needed > newlen)
 7666 tgl@sss.pgh.pa.us         339                 :         116124 :         newlen = 2 * newlen;
                                340                 :                : 
                                341                 :                :     /*
                                342                 :                :      * Clamp to MaxAllocSize in case we went past it.  Note we are assuming
                                343                 :                :      * here that MaxAllocSize <= INT_MAX/2, else the above loop could
                                344                 :                :      * overflow.  We will still have newlen >= needed.
                                345                 :                :      */
 2531 alvherre@alvh.no-ip.      346         [ -  + ]:          92872 :     if (newlen > (int) MaxAllocSize)
 2531 alvherre@alvh.no-ip.      347                 :UBC           0 :         newlen = (int) MaxAllocSize;
                                348                 :                : 
 2531 alvherre@alvh.no-ip.      349                 :CBC       92872 :     str->data = (char *) repalloc(str->data, newlen);
                                350                 :                : 
 7666 tgl@sss.pgh.pa.us         351                 :          92872 :     str->maxlen = newlen;
                                352                 :                : }
                                353                 :                : 
                                354                 :                : /*
                                355                 :                :  * destroyStringInfo
                                356                 :                :  *
                                357                 :                :  * Frees a StringInfo and its buffer (opposite of makeStringInfo()).
                                358                 :                :  * This must only be called on palloc'd StringInfos.
                                359                 :                :  */
                                360                 :                : void
   29 dgustafsson@postgres      361                 :GNC        3569 : destroyStringInfo(StringInfo str)
                                362                 :                : {
                                363                 :                :     /* don't allow destroys of read-only StringInfos */
                                364         [ -  + ]:           3569 :     Assert(str->maxlen != 0);
                                365                 :                : 
                                366                 :           3569 :     pfree(str->data);
                                367                 :           3569 :     pfree(str);
                                368                 :           3569 : }
        

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