1/*-------------------------------------------------------------------------
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).
10 * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group
11 * Portions Copyright (c) 1994, Regents of the University of California
13 * src/common/stringinfo.c
15 *-------------------------------------------------------------------------
33 * initStringInfoInternal
35 * Initialize a StringInfoData struct (with previously undefined contents)
36 * to describe an empty string.
37 * The initial memory allocation size is specified by 'initsize'.
38 * The valid range for 'initsize' is 1 to MaxAllocSize.
46 str->maxlen = initsize;
51 * makeStringInfoInternal(int initsize)
53 * Create an empty 'StringInfoData' & return a pointer to it.
54 * The initial memory allocation size is specified by 'initsize'.
55 * The valid range for 'initsize' is 1 to MaxAllocSize.
69 * Create an empty 'StringInfoData' & return a pointer to it.
78 * makeStringInfoExt(int initsize)
80 * Create an empty 'StringInfoData' & return a pointer to it.
81 * The initial memory allocation size is specified by 'initsize'.
82 * The valid range for 'initsize' is 1 to MaxAllocSize.
93 * Initialize a StringInfoData struct (with previously undefined contents)
94 * to describe an empty string.
105 * Initialize a StringInfoData struct (with previously undefined contents)
106 * to describe an empty string.
107 * The initial memory allocation size is specified by 'initsize'.
108 * The valid range for 'initsize' is 1 to MaxAllocSize.
119 * Reset the StringInfo: the data buffer remains valid, but its
120 * previous content, if any, is cleared.
122 * Read-only StringInfos as initialized by initReadOnlyStringInfo cannot be
128 /* don't allow resets of read-only StringInfos */
139 * Format text data under the control of fmt (an sprintf-style format string)
140 * and append it to whatever is already in str. More space is allocated
141 * to str if necessary. This is sort of like a combination of sprintf and
147 int save_errno = errno;
154 /* Try to format the data. */
163 /* Increase the buffer size and try again. */
171 * Attempt to format text data under the control of fmt (an sprintf-style
172 * format string) and append it to whatever is already in str. If successful
173 * return zero; if not (because there's not enough space), return an estimate
174 * of the space needed, without modifying str. Typically the caller should
175 * pass the return value to enlargeStringInfo() before trying again; see
176 * appendStringInfo for standard usage pattern.
178 * Caution: callers must be sure to preserve their entry-time errno
179 * when looping, in case the fmt contains "%m".
181 * XXX This API is ugly, but there seems no alternative given the C spec's
182 * restrictions on what can portably be done with va_list arguments: you have
183 * to redo va_start before you can rescan the argument list, and we can't do
195 * If there's hardly any space, don't bother trying, just fail to make the
196 * caller enlarge the buffer first. We have to guess at how much to
197 * enlarge, since we're skipping the formatting work.
199 avail =
str->maxlen -
str->len;
205 if (nprinted < (
size_t) avail)
207 /* Success. Note nprinted does not include trailing null. */
208 str->len += (int) nprinted;
212 /* Restore the trailing null so that str is unmodified. */
213 str->data[
str->len] =
'0円';
216 * Return pvsnprintf's estimate of the space needed. (Although this is
217 * given as a size_t, we know it will fit in int because it's not more
218 * than MaxAllocSize.)
220 return (
int) nprinted;
224 * appendStringInfoString
226 * Append a null-terminated string to str.
227 * Like appendStringInfo(str, "%s", s) but faster.
236 * appendStringInfoChar
238 * Append a single byte to str.
239 * Like appendStringInfo(str, "%c", ch) but much faster.
244 /* Make more room if needed */
245 if (
str->len + 1 >=
str->maxlen)
248 /* OK, append the character */
251 str->data[
str->len] =
'0円';
255 * appendStringInfoSpaces
257 * Append the specified number of spaces to a buffer.
264 /* Make more room if needed */
267 /* OK, append the spaces */
268 memset(&
str->data[
str->len],
' ', count);
270 str->data[
str->len] =
'0円';
275 * appendBinaryStringInfo
277 * Append arbitrary binary data to a StringInfo, allocating more space
278 * if necessary. Ensures that a trailing null byte is present.
285 /* Make more room if needed */
288 /* OK, append the data */
293 * Keep a trailing null in place, even though it's probably useless for
294 * binary data. (Some callers are dealing with text but call this because
295 * their input isn't null-terminated.)
297 str->data[
str->len] =
'0円';
301 * appendBinaryStringInfoNT
303 * Append arbitrary binary data to a StringInfo, allocating more space
304 * if necessary. Does not ensure a trailing null-byte exists.
311 /* Make more room if needed */
314 /* OK, append the data */
322 * Make sure there is enough space for 'needed' more bytes
323 * ('needed' does not include the terminating null).
325 * External callers usually need not concern themselves with this, since
326 * all stringinfo.c routines do it automatically. However, if a caller
327 * knows that a StringInfo will eventually become X bytes large, it
328 * can save some palloc overhead by enlarging the buffer before starting
329 * to store data in it.
331 * NB: In the backend, because we use repalloc() to enlarge the buffer, the
332 * string buffer will remain allocated in the same memory context that was
333 * current when initStringInfo was called, even if another context is now
334 * current. This is the desired and indeed critical behavior!
341 /* validate this is not a read-only StringInfo */
345 * Guard against out-of-range "needed" values. Without this, we can get
346 * an overflow or infinite loop in the following.
348 if (needed < 0)
/* should not happen */
351 elog(
ERROR,
"invalid string enlargement request size: %d", needed);
353 fprintf(stderr,
"invalid string enlargement request size: %d\n", needed);
361 (
errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
363 errdetail(
"Cannot enlarge string buffer containing %d bytes by %d more bytes.",
367 _(
"string buffer exceeds maximum allowed length (%zu bytes)\n\nCannot enlarge string buffer containing %d bytes by %d more bytes.\n"),
373 needed +=
str->len + 1;
/* total space required now */
375 /* Because of the above test, we now have needed <= MaxAllocSize */
377 if (needed <= str->maxlen)
378 return;
/* got enough space already */
381 * We don't want to allocate just a little more space with each append;
382 * for efficiency, double the buffer size each time it overflows.
383 * Actually, we might need to more than double it if 'needed' is big...
385 newlen = 2 *
str->maxlen;
386 while (needed > newlen)
390 * Clamp to MaxAllocSize in case we went past it. Note we are assuming
391 * here that MaxAllocSize <= INT_MAX/2, else the above loop could
392 * overflow. We will still have newlen >= needed.
399 str->maxlen = newlen;
405 * Frees a StringInfo and its buffer (opposite of makeStringInfo()).
406 * This must only be called on palloc'd StringInfos.
411 /* don't allow destroys of read-only StringInfos */
#define fprintf(file, fmt, msg)
int errdetail(const char *fmt,...)
int errcode(int sqlerrcode)
int errmsg(const char *fmt,...)
#define ereport(elevel,...)
Assert(PointerIsAligned(start, uint64))
void * repalloc(void *pointer, Size size)
void pfree(void *pointer)
size_t pvsnprintf(char *buf, size_t len, const char *fmt, va_list args)
struct StringInfoData * StringInfo
int appendStringInfoVA(StringInfo str, const char *fmt, va_list args)
void destroyStringInfo(StringInfo str)
StringInfo makeStringInfo(void)
static void initStringInfoInternal(StringInfo str, int initsize)
void resetStringInfo(StringInfo str)
void appendStringInfo(StringInfo str, const char *fmt,...)
void enlargeStringInfo(StringInfo str, int needed)
StringInfo makeStringInfoExt(int initsize)
void appendBinaryStringInfoNT(StringInfo str, const void *data, int datalen)
void appendBinaryStringInfo(StringInfo str, const void *data, int datalen)
static StringInfo makeStringInfoInternal(int initsize)
void appendStringInfoSpaces(StringInfo str, int count)
void initStringInfoExt(StringInfo str, int initsize)
void appendStringInfoString(StringInfo str, const char *s)
void appendStringInfoChar(StringInfo str, char ch)
void initStringInfo(StringInfo str)
#define STRINGINFO_DEFAULT_SIZE