Files
postgresql/src/include/lib/stringinfo.h
Tom Lane 3147acd63e Use improved vsnprintf calling logic in more places.
When we are using a C99-compliant vsnprintf implementation (which should be
most places, these days) it is worth the trouble to make use of its report
of how large the buffer needs to be to succeed.  This patch adjusts
stringinfo.c and some miscellaneous usages in pg_dump to do that, relying
on the logic recently added in libpgcommon's psprintf.c.  Since these
places want to know the number of bytes written once we succeed, modify the
API of pvsnprintf() to report that.

There remains near-duplicate logic in pqexpbuffer.c, but since that code
is in libpq, psprintf.c's approach of exit()-on-error isn't appropriate
for use there.  Also note that I didn't bother touching the multitude
of places that call (v)snprintf without any attempt to provide a resizable
buffer.

Release-note-worthy incompatibility: the API of appendStringInfoVA()
changed.  If there's any third-party code that's calling that directly,
it will need tweaking along the same lines as in this patch.

David Rowley and Tom Lane
2013-10-24 21:43:57 -04:00

158 lines
5.4 KiB
C

/*-------------------------------------------------------------------------
*
* stringinfo.h
* Declarations/definitions for "StringInfo" functions.
*
* 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-2013, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* src/include/lib/stringinfo.h
*
*-------------------------------------------------------------------------
*/
#ifndef STRINGINFO_H
#define STRINGINFO_H
/*-------------------------
* StringInfoData holds information about an extensible string.
* data is the current buffer for the string (allocated with palloc).
* len is the current string length. There is guaranteed to be
* a terminating '\0' at data[len], although this is not very
* useful when the string holds binary data rather than text.
* maxlen is the allocated size in bytes of 'data', i.e. the maximum
* string size (including the terminating '\0' char) that we can
* currently store in 'data' without having to reallocate
* more space. We must always have maxlen > len.
* cursor is initialized to zero by makeStringInfo or initStringInfo,
* but is not otherwise touched by the stringinfo.c routines.
* Some routines use it to scan through a StringInfo.
*-------------------------
*/
typedef struct StringInfoData
{
char *data;
int len;
int maxlen;
int cursor;
} StringInfoData;
typedef StringInfoData *StringInfo;
/*------------------------
* There are two ways to create a StringInfo object initially:
*
* StringInfo stringptr = makeStringInfo();
* Both the StringInfoData and the data buffer are palloc'd.
*
* StringInfoData string;
* initStringInfo(&string);
* The data buffer is palloc'd but the StringInfoData is just local.
* This is the easiest approach for a StringInfo object that will
* only live as long as the current routine.
*
* To destroy a StringInfo, pfree() the data buffer, and then pfree() the
* StringInfoData if it was palloc'd. There's no special support for this.
*
* NOTE: some routines build up a string using StringInfo, and then
* release the StringInfoData but return the data string itself to their
* caller. At that point the data string looks like a plain palloc'd
* string.
*-------------------------
*/
/*------------------------
* makeStringInfo
* Create an empty 'StringInfoData' & return a pointer to it.
*/
extern StringInfo makeStringInfo(void);
/*------------------------
* initStringInfo
* Initialize a StringInfoData struct (with previously undefined contents)
* to describe an empty string.
*/
extern void initStringInfo(StringInfo str);
/*------------------------
* resetStringInfo
* Clears the current content of the StringInfo, if any. The
* StringInfo remains valid.
*/
extern void resetStringInfo(StringInfo str);
/*------------------------
* 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.
*/
extern void
appendStringInfo(StringInfo str, const char *fmt,...)
/* This extension allows gcc to check the format string */
__attribute__((format(PG_PRINTF_ATTRIBUTE, 2, 3)));
/*------------------------
* 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.
*/
extern int
appendStringInfoVA(StringInfo str, const char *fmt, va_list args)
__attribute__((format(PG_PRINTF_ATTRIBUTE, 2, 0)));
/*------------------------
* appendStringInfoString
* Append a null-terminated string to str.
* Like appendStringInfo(str, "%s", s) but faster.
*/
extern void appendStringInfoString(StringInfo str, const char *s);
/*------------------------
* appendStringInfoChar
* Append a single byte to str.
* Like appendStringInfo(str, "%c", ch) but much faster.
*/
extern void appendStringInfoChar(StringInfo str, char ch);
/*------------------------
* appendStringInfoCharMacro
* As above, but a macro for even more speed where it matters.
* Caution: str argument will be evaluated multiple times.
*/
#define appendStringInfoCharMacro(str,ch) \
(((str)->len + 1 >= (str)->maxlen) ? \
appendStringInfoChar(str, ch) : \
(void)((str)->data[(str)->len] = (ch), (str)->data[++(str)->len] = '\0'))
/*------------------------
* appendStringInfoSpaces
* Append a given number of spaces to str.
*/
extern void appendStringInfoSpaces(StringInfo str, int count);
/*------------------------
* appendBinaryStringInfo
* Append arbitrary binary data to a StringInfo, allocating more space
* if necessary.
*/
extern void appendBinaryStringInfo(StringInfo str,
const char *data, int datalen);
/*------------------------
* enlargeStringInfo
* Make sure a StringInfo's buffer can hold at least 'needed' more bytes.
*/
extern void enlargeStringInfo(StringInfo str, int needed);
#endif /* STRINGINFO_H */