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-2026, 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 475459 : initReadOnlyStringInfo(StringInfo str, char *data, int len)
158 : {
159 475459 : str->data = data;
160 475459 : str->len = len;
161 475459 : str->maxlen = 0; /* read-only */
162 475459 : str->cursor = 0;
163 475459 : }
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 257647 : initStringInfoFromString(StringInfo str, char *data, int len)
176 : {
177 : Assert(data[len] == '\0');
178 :
179 257647 : str->data = data;
180 257647 : str->len = len;
181 257647 : str->maxlen = len + 1;
182 257647 : str->cursor = 0;
183 257647 : }
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 */
|