diff options
Diffstat (limited to 'src/backend/lib/stringinfo.c')
-rw-r--r-- | src/backend/lib/stringinfo.c | 314 |
1 files changed, 0 insertions, 314 deletions
diff --git a/src/backend/lib/stringinfo.c b/src/backend/lib/stringinfo.c deleted file mode 100644 index 99c83c1549c..00000000000 --- a/src/backend/lib/stringinfo.c +++ /dev/null @@ -1,314 +0,0 @@ -/*------------------------------------------------------------------------- - * - * stringinfo.c - * - * StringInfo provides an indefinitely-extensible string data type. - * It can be used to buffer either ordinary C strings (null-terminated text) - * or arbitrary binary data. All storage is allocated with palloc(). - * - * Portions Copyright (c) 1996-2019, PostgreSQL Global Development Group - * Portions Copyright (c) 1994, Regents of the University of California - * - * src/backend/lib/stringinfo.c - * - *------------------------------------------------------------------------- - */ -#include "postgres.h" - -#include "lib/stringinfo.h" -#include "utils/memutils.h" - - -/* - * makeStringInfo - * - * Create an empty 'StringInfoData' & return a pointer to it. - */ -StringInfo -makeStringInfo(void) -{ - StringInfo res; - - res = (StringInfo) palloc(sizeof(StringInfoData)); - - initStringInfo(res); - - return res; -} - -/* - * initStringInfo - * - * Initialize a StringInfoData struct (with previously undefined contents) - * to describe an empty string. - */ -void -initStringInfo(StringInfo str) -{ - int size = 1024; /* initial default buffer size */ - - str->data = (char *) palloc(size); - str->maxlen = size; - resetStringInfo(str); -} - -/* - * resetStringInfo - * - * Reset the StringInfo: the data buffer remains valid, but its - * previous content, if any, is cleared. - */ -void -resetStringInfo(StringInfo str) -{ - str->data[0] = '\0'; - str->len = 0; - str->cursor = 0; -} - -/* - * appendStringInfo - * - * Format text data under the control of fmt (an sprintf-style format string) - * and append it to whatever is already in str. More space is allocated - * to str if necessary. This is sort of like a combination of sprintf and - * strcat. - */ -void -appendStringInfo(StringInfo str, const char *fmt,...) -{ - int save_errno = errno; - - for (;;) - { - va_list args; - int needed; - - /* Try to format the data. */ - errno = save_errno; - va_start(args, fmt); - needed = appendStringInfoVA(str, fmt, args); - va_end(args); - - if (needed == 0) - break; /* success */ - - /* Increase the buffer size and try again. */ - enlargeStringInfo(str, needed); - } -} - -/* - * appendStringInfoVA - * - * Attempt to format text data under the control of fmt (an sprintf-style - * format string) and append it to whatever is already in str. If successful - * return zero; if not (because there's not enough space), return an estimate - * of the space needed, without modifying str. Typically the caller should - * pass the return value to enlargeStringInfo() before trying again; see - * appendStringInfo for standard usage pattern. - * - * Caution: callers must be sure to preserve their entry-time errno - * when looping, in case the fmt contains "%m". - * - * XXX This API is ugly, but there seems no alternative given the C spec's - * restrictions on what can portably be done with va_list arguments: you have - * to redo va_start before you can rescan the argument list, and we can't do - * that from here. - */ -int -appendStringInfoVA(StringInfo str, const char *fmt, va_list args) -{ - int avail; - size_t nprinted; - - Assert(str != NULL); - - /* - * If there's hardly any space, don't bother trying, just fail to make the - * caller enlarge the buffer first. We have to guess at how much to - * enlarge, since we're skipping the formatting work. - */ - avail = str->maxlen - str->len; - if (avail < 16) - return 32; - - nprinted = pvsnprintf(str->data + str->len, (size_t) avail, fmt, args); - - if (nprinted < (size_t) avail) - { - /* Success. Note nprinted does not include trailing null. */ - str->len += (int) nprinted; - return 0; - } - - /* Restore the trailing null so that str is unmodified. */ - str->data[str->len] = '\0'; - - /* - * Return pvsnprintf's estimate of the space needed. (Although this is - * given as a size_t, we know it will fit in int because it's not more - * than MaxAllocSize.) - */ - return (int) nprinted; -} - -/* - * appendStringInfoString - * - * Append a null-terminated string to str. - * Like appendStringInfo(str, "%s", s) but faster. - */ -void -appendStringInfoString(StringInfo str, const char *s) -{ - appendBinaryStringInfo(str, s, strlen(s)); -} - -/* - * appendStringInfoChar - * - * Append a single byte to str. - * Like appendStringInfo(str, "%c", ch) but much faster. - */ -void -appendStringInfoChar(StringInfo str, char ch) -{ - /* Make more room if needed */ - if (str->len + 1 >= str->maxlen) - enlargeStringInfo(str, 1); - - /* OK, append the character */ - str->data[str->len] = ch; - str->len++; - str->data[str->len] = '\0'; -} - -/* - * appendStringInfoSpaces - * - * Append the specified number of spaces to a buffer. - */ -void -appendStringInfoSpaces(StringInfo str, int count) -{ - if (count > 0) - { - /* Make more room if needed */ - enlargeStringInfo(str, count); - - /* OK, append the spaces */ - while (--count >= 0) - str->data[str->len++] = ' '; - str->data[str->len] = '\0'; - } -} - -/* - * appendBinaryStringInfo - * - * Append arbitrary binary data to a StringInfo, allocating more space - * if necessary. Ensures that a trailing null byte is present. - */ -void -appendBinaryStringInfo(StringInfo str, const char *data, int datalen) -{ - Assert(str != NULL); - - /* Make more room if needed */ - enlargeStringInfo(str, datalen); - - /* OK, append the data */ - memcpy(str->data + str->len, data, datalen); - str->len += datalen; - - /* - * Keep a trailing null in place, even though it's probably useless for - * binary data. (Some callers are dealing with text but call this because - * their input isn't null-terminated.) - */ - str->data[str->len] = '\0'; -} - -/* - * appendBinaryStringInfoNT - * - * Append arbitrary binary data to a StringInfo, allocating more space - * if necessary. Does not ensure a trailing null-byte exists. - */ -void -appendBinaryStringInfoNT(StringInfo str, const char *data, int datalen) -{ - Assert(str != NULL); - - /* Make more room if needed */ - enlargeStringInfo(str, datalen); - - /* OK, append the data */ - memcpy(str->data + str->len, data, datalen); - str->len += datalen; -} - -/* - * enlargeStringInfo - * - * Make sure there is enough space for 'needed' more bytes - * ('needed' does not include the terminating null). - * - * External callers usually need not concern themselves with this, since - * all stringinfo.c routines do it automatically. However, if a caller - * knows that a StringInfo will eventually become X bytes large, it - * can save some palloc overhead by enlarging the buffer before starting - * to store data in it. - * - * NB: because we use repalloc() to enlarge the buffer, the string buffer - * will remain allocated in the same memory context that was current when - * initStringInfo was called, even if another context is now current. - * This is the desired and indeed critical behavior! - */ -void -enlargeStringInfo(StringInfo str, int needed) -{ - int newlen; - - /* - * Guard against out-of-range "needed" values. Without this, we can get - * an overflow or infinite loop in the following. - */ - if (needed < 0) /* should not happen */ - elog(ERROR, "invalid string enlargement request size: %d", needed); - if (((Size) needed) >= (MaxAllocSize - (Size) str->len)) - ereport(ERROR, - (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED), - errmsg("out of memory"), - errdetail("Cannot enlarge string buffer containing %d bytes by %d more bytes.", - str->len, needed))); - - needed += str->len + 1; /* total space required now */ - - /* Because of the above test, we now have needed <= MaxAllocSize */ - - if (needed <= str->maxlen) - return; /* got enough space already */ - - /* - * We don't want to allocate just a little more space with each append; - * for efficiency, double the buffer size each time it overflows. - * Actually, we might need to more than double it if 'needed' is big... - */ - newlen = 2 * str->maxlen; - while (needed > newlen) - newlen = 2 * newlen; - - /* - * Clamp to MaxAllocSize in case we went past it. Note we are assuming - * here that MaxAllocSize <= INT_MAX/2, else the above loop could - * overflow. We will still have newlen >= needed. - */ - if (newlen > (int) MaxAllocSize) - newlen = (int) MaxAllocSize; - - str->data = (char *) repalloc(str->data, newlen); - - str->maxlen = newlen; -} |