Line data Source code
1 : /*------------------------------------------------------------------------- 2 : * 3 : * stringinfo.h 4 : * Declarations/definitions for "StringInfo" functions. 5 : * 6 : * StringInfo provides an extensible string data type (currently limited to a 7 : * length of 1GB). It can be used to buffer either ordinary C strings 8 : * (null-terminated text) or arbitrary binary data. All storage is allocated 9 : * with palloc() (falling back to malloc in frontend code). 10 : * 11 : * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group 12 : * Portions Copyright (c) 1994, Regents of the University of California 13 : * 14 : * src/include/lib/stringinfo.h 15 : * 16 : *------------------------------------------------------------------------- 17 : */ 18 : #ifndef STRINGINFO_H 19 : #define STRINGINFO_H 20 : 21 : /*------------------------- 22 : * StringInfoData holds information about an extensible string. 23 : * data is the current buffer for the string. 24 : * len is the current string length. Except in the case of read-only 25 : * strings described below, there is guaranteed to be a 26 : * terminating '\0' at data[len]. 27 : * maxlen is the allocated size in bytes of 'data', i.e. the maximum 28 : * string size (including the terminating '\0' char) that we can 29 : * currently store in 'data' without having to reallocate 30 : * more space. We must always have maxlen > len, except 31 : * in the read-only case described below. 32 : * cursor is initialized to zero by makeStringInfo, initStringInfo, 33 : * initReadOnlyStringInfo and initStringInfoFromString but is not 34 : * otherwise touched by the stringinfo.c routines. Some routines 35 : * use it to scan through a StringInfo. 36 : * 37 : * As a special case, a StringInfoData can be initialized with a read-only 38 : * string buffer. In this case "data" does not necessarily point at a 39 : * palloc'd chunk, and management of the buffer storage is the caller's 40 : * responsibility. maxlen is set to zero to indicate that this is the case. 41 : * Read-only StringInfoDatas cannot be appended to or reset. 42 : * Also, it is caller's option whether a read-only string buffer has a 43 : * terminating '\0' or not. This depends on the intended usage. 44 : *------------------------- 45 : */ 46 : typedef struct StringInfoData 47 : { 48 : char *data; 49 : int len; 50 : int maxlen; 51 : int cursor; 52 : } StringInfoData; 53 : 54 : typedef StringInfoData *StringInfo; 55 : 56 : 57 : /*------------------------ 58 : * There are six ways to create a StringInfo object initially: 59 : * 60 : * StringInfo stringptr = makeStringInfo(); 61 : * Both the StringInfoData and the data buffer are palloc'd. 62 : * 63 : * StringInfo stringptr = makeStringInfoExt(initsize); 64 : * Same as makeStringInfo except the data buffer is allocated 65 : * with size 'initsize'. 66 : * 67 : * StringInfoData string; 68 : * initStringInfo(&string); 69 : * The data buffer is palloc'd but the StringInfoData is just local. 70 : * This is the easiest approach for a StringInfo object that will 71 : * only live as long as the current routine. 72 : * 73 : * StringInfoData string; 74 : * initStringInfoExt(&string, initsize); 75 : * Same as initStringInfo except the data buffer is allocated 76 : * with size 'initsize'. 77 : * 78 : * StringInfoData string; 79 : * initReadOnlyStringInfo(&string, existingbuf, len); 80 : * The StringInfoData's data field is set to point directly to the 81 : * existing buffer and the StringInfoData's len is set to the given len. 82 : * The given buffer can point to memory that's not managed by palloc or 83 : * is pointing partway through a palloc'd chunk. The maxlen field is set 84 : * to 0. A read-only StringInfo cannot be appended to using any of the 85 : * appendStringInfo functions or reset with resetStringInfo(). The given 86 : * buffer can optionally omit the trailing NUL. 87 : * 88 : * StringInfoData string; 89 : * initStringInfoFromString(&string, palloced_buf, len); 90 : * The StringInfoData's data field is set to point directly to the given 91 : * buffer and the StringInfoData's len is set to the given len. This 92 : * method of initialization is useful when the buffer already exists. 93 : * StringInfos initialized this way can be appended to using the 94 : * appendStringInfo functions and reset with resetStringInfo(). The 95 : * given buffer must be NUL-terminated. The palloc'd buffer is assumed 96 : * to be len + 1 in size. 97 : * 98 : * To destroy a StringInfo, pfree() the data buffer, and then pfree() the 99 : * StringInfoData if it was palloc'd. For StringInfos created with 100 : * makeStringInfo(), destroyStringInfo() is provided for this purpose. 101 : * However, if the StringInfo was initialized using initReadOnlyStringInfo() 102 : * then the caller will need to consider if it is safe to pfree the data 103 : * buffer. 104 : * 105 : * NOTE: some routines build up a string using StringInfo, and then 106 : * release the StringInfoData but return the data string itself to their 107 : * caller. At that point the data string looks like a plain palloc'd 108 : * string. 109 : *------------------------- 110 : */ 111 : 112 : #define STRINGINFO_DEFAULT_SIZE 1024 /* default initial allocation size */ 113 : 114 : /*------------------------ 115 : * makeStringInfo 116 : * Create an empty 'StringInfoData' & return a pointer to it. 117 : */ 118 : extern StringInfo makeStringInfo(void); 119 : 120 : /*------------------------ 121 : * makeStringInfoExt 122 : * Create an empty 'StringInfoData' & return a pointer to it. 123 : * The data buffer is allocated with size 'initsize'. 124 : * The valid range for 'initsize' is 1 to MaxAllocSize. 125 : */ 126 : extern StringInfo makeStringInfoExt(int initsize); 127 : 128 : /*------------------------ 129 : * initStringInfo 130 : * Initialize a StringInfoData struct (with previously undefined contents) 131 : * to describe an empty string. 132 : */ 133 : extern void initStringInfo(StringInfo str); 134 : 135 : /*------------------------ 136 : * initStringInfoExt 137 : * Initialize a StringInfoData struct (with previously undefined contents) to 138 : * describe an empty string. The data buffer is allocated with size 139 : * 'initsize'. The valid range for 'initsize' is 1 to MaxAllocSize. 140 : */ 141 : extern void initStringInfoExt(StringInfo str, int initsize); 142 : 143 : /*------------------------ 144 : * initReadOnlyStringInfo 145 : * Initialize a StringInfoData struct from an existing string without copying 146 : * the string. The caller is responsible for ensuring the given string 147 : * remains valid as long as the StringInfoData does. Calls to this are used 148 : * in performance critical locations where allocating a new buffer and copying 149 : * would be too costly. Read-only StringInfoData's may not be appended to 150 : * using any of the appendStringInfo functions or reset with 151 : * resetStringInfo(). 152 : * 153 : * 'data' does not need to point directly to a palloc'd chunk of memory and may 154 : * omit the NUL termination character at data[len]. 155 : */ 156 : static inline void 157 890478 : initReadOnlyStringInfo(StringInfo str, char *data, int len) 158 : { 159 890478 : str->data = data; 160 890478 : str->len = len; 161 890478 : str->maxlen = 0; /* read-only */ 162 890478 : str->cursor = 0; 163 890478 : } 164 : 165 : /*------------------------ 166 : * initStringInfoFromString 167 : * Initialize a StringInfoData struct from an existing string without copying 168 : * the string. 'data' must be a valid palloc'd chunk of memory that can have 169 : * repalloc() called should more space be required during a call to any of the 170 : * appendStringInfo functions. 171 : * 172 : * 'data' must be NUL terminated at 'len' bytes. 173 : */ 174 : static inline void 175 505788 : initStringInfoFromString(StringInfo str, char *data, int len) 176 : { 177 : Assert(data[len] == '\0'); 178 : 179 505788 : str->data = data; 180 505788 : str->len = len; 181 505788 : str->maxlen = len + 1; 182 505788 : str->cursor = 0; 183 505788 : } 184 : 185 : /*------------------------ 186 : * resetStringInfo 187 : * Clears the current content of the StringInfo, if any. The 188 : * StringInfo remains valid. 189 : */ 190 : extern void resetStringInfo(StringInfo str); 191 : 192 : /*------------------------ 193 : * appendStringInfo 194 : * Format text data under the control of fmt (an sprintf-style format string) 195 : * and append it to whatever is already in str. More space is allocated 196 : * to str if necessary. This is sort of like a combination of sprintf and 197 : * strcat. 198 : */ 199 : extern void appendStringInfo(StringInfo str, const char *fmt,...) pg_attribute_printf(2, 3); 200 : 201 : /*------------------------ 202 : * appendStringInfoVA 203 : * Attempt to format text data under the control of fmt (an sprintf-style 204 : * format string) and append it to whatever is already in str. If successful 205 : * return zero; if not (because there's not enough space), return an estimate 206 : * of the space needed, without modifying str. Typically the caller should 207 : * pass the return value to enlargeStringInfo() before trying again; see 208 : * appendStringInfo for standard usage pattern. 209 : */ 210 : extern int appendStringInfoVA(StringInfo str, const char *fmt, va_list args) pg_attribute_printf(2, 0); 211 : 212 : /*------------------------ 213 : * appendStringInfoString 214 : * Append a null-terminated string to str. 215 : * Like appendStringInfo(str, "%s", s) but faster. 216 : */ 217 : extern void appendStringInfoString(StringInfo str, const char *s); 218 : 219 : /*------------------------ 220 : * appendStringInfoChar 221 : * Append a single byte to str. 222 : * Like appendStringInfo(str, "%c", ch) but much faster. 223 : */ 224 : extern void appendStringInfoChar(StringInfo str, char ch); 225 : 226 : /*------------------------ 227 : * appendStringInfoCharMacro 228 : * As above, but a macro for even more speed where it matters. 229 : * Caution: str argument will be evaluated multiple times. 230 : */ 231 : #define appendStringInfoCharMacro(str,ch) \ 232 : (((str)->len + 1 >= (str)->maxlen) ? \ 233 : appendStringInfoChar(str, ch) : \ 234 : (void)((str)->data[(str)->len] = (ch), (str)->data[++(str)->len] = '\0')) 235 : 236 : /*------------------------ 237 : * appendStringInfoSpaces 238 : * Append a given number of spaces to str. 239 : */ 240 : extern void appendStringInfoSpaces(StringInfo str, int count); 241 : 242 : /*------------------------ 243 : * appendBinaryStringInfo 244 : * Append arbitrary binary data to a StringInfo, allocating more space 245 : * if necessary. 246 : */ 247 : extern void appendBinaryStringInfo(StringInfo str, 248 : const void *data, int datalen); 249 : 250 : /*------------------------ 251 : * appendBinaryStringInfoNT 252 : * Append arbitrary binary data to a StringInfo, allocating more space 253 : * if necessary. Does not ensure a trailing null-byte exists. 254 : */ 255 : extern void appendBinaryStringInfoNT(StringInfo str, 256 : const void *data, int datalen); 257 : 258 : /*------------------------ 259 : * enlargeStringInfo 260 : * Make sure a StringInfo's buffer can hold at least 'needed' more bytes. 261 : */ 262 : extern void enlargeStringInfo(StringInfo str, int needed); 263 : 264 : /*------------------------ 265 : * destroyStringInfo 266 : * Frees a StringInfo and its buffer (opposite of makeStringInfo()). 267 : */ 268 : extern void destroyStringInfo(StringInfo str); 269 : 270 : #endif /* STRINGINFO_H */