c9f247af创建于 2024年7月29日历史提交
/* -------------------------------------------------------------------------
 *
 * 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-2012, 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);

/* destroy a 'StringInfoData', use this function when call makeStringInfo */
extern void DestroyStringInfo(StringInfo str);

/* ------------------------
 * initStringInfo
 * Initialize a StringInfoData struct (with previously undefined contents)
 * to describe an empty string.
 */
extern void initStringInfo(StringInfo str);

/* free a 'StringInfoData', use this function when call initStringInfo */
extern void FreeStringInfo(StringInfo str);

/* ------------------------
 * resetStringInfo
 * Clears the current content of the StringInfo, if any. The
 * StringInfo remains valid.
 */
inline 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.
 */
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 true; if not (because there's not enough space), return false
 * without modifying str.  Typically the caller would enlarge str and retry
 * on false return --- see appendStringInfo for standard usage pattern.
 */
extern bool 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);

/* ------------------------
 * popStringInfoChar
 * Pop a single byte to str..
 */
extern void popStringInfoChar(StringInfo str);

/* ------------------------
 * 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);

/*------------------------
 * appendBinaryStringInfoNT
 * Append arbitrary binary data to a StringInfo, allocating more space
 * if necessary. Does not ensure a trailing null-byte exists.
 */
extern void appendBinaryStringInfoNT(StringInfo str, const char *data, int datalen);

extern void copyStringInfo(StringInfo to, StringInfo from);

/* ------------------------
 * enlargeBuffer
 * Make sure a buffer can hold at least 'needed' more bytes.
 */
void enlargeBuffer(int needed, int len, int* maxlen, char** data);

void enlargeBufferSize(int needed, int len, size_t* maxlen, char** data);

/* ------------------------
 * enlargeStringInfo
 *
 * Make sure there is enough space for StringInfo
 *
 * 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.
 */
inline void enlargeStringInfo(StringInfo str, int needed)
{
    enlargeBuffer(needed, str->len, &str->maxlen, &str->data);
}

/*
 * The following function is used to request the use of more than 1GB of memory
 */

/* -------------------------
 * StringInfoDataHuge 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 StringInfoDataHuge {
    char* data;
    int64 len;
    int64 maxlen;
    int64 cursor;
} StringInfoDataHuge;

typedef StringInfoDataHuge* StringInfoHuge;


/* ------------------------
 * initStringInfoHuge
 * Initialize a StringInfoDataHuge struct (with previously undefined contents)
 * to describe an empty string.
 */
extern void initStringInfoHuge(StringInfoHuge str);

/* free a 'StringInfoDataHuge', use this function when call initStringInfo */
extern void FreeStringInfoHuge(StringInfoHuge str);

/* ------------------------
 * resetStringInfoHuge
 * Clears the current content of the StringInfoHuge, if any. The
 * StringInfo remains valid.
 */
extern void resetStringInfoHuge(StringInfoHuge str);

/* ------------------------
 * enlargeBufferHuge
 * Make sure a buffer can hold at least 'needed' more bytes.
 */
void enlargeBufferHuge(int64 needed, int64 len, int64* maxlen, char** data);

/* ------------------------
 * enlargeStringInfoHuge
 * Make sure a StringInfoHuge's buffer can hold at least 'needed' more bytes.
 */
extern void enlargeStringInfoHuge(StringInfoHuge str, int64 needed);

/* ------------------------
 * appendStringInfoHugeVA
 * 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 true; if not (because there's not enough space), return false
 * without modifying str.  Typically the caller would enlarge str and retry
 * on false return --- see appendStringInfo for standard usage pattern.
 */
extern bool appendStringInfoHugeVA(StringInfoHuge str, const char* fmt, va_list args)
    __attribute__((format(PG_PRINTF_ATTRIBUTE, 2, 0)));

/* ------------------------
 * appendStringInfoHuge
 * 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 appendStringInfoHuge(StringInfoHuge str, const char* fmt, ...)
    /* This extension allows gcc to check the format string */
    __attribute__((format(PG_PRINTF_ATTRIBUTE, 2, 3)));

extern char *psprintf(const char *fmt,...) __attribute__((format(PG_PRINTF_ATTRIBUTE, 1, 2))); 
#endif /* STRINGINFO_H */