Age Owner Branch data TLA 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-2024, 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 four 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 : : * StringInfoData string;
64 : : * initStringInfo(&string);
65 : : * The data buffer is palloc'd but the StringInfoData is just local.
66 : : * This is the easiest approach for a StringInfo object that will
67 : : * only live as long as the current routine.
68 : : *
69 : : * StringInfoData string;
70 : : * initReadOnlyStringInfo(&string, existingbuf, len);
71 : : * The StringInfoData's data field is set to point directly to the
72 : : * existing buffer and the StringInfoData's len is set to the given len.
73 : : * The given buffer can point to memory that's not managed by palloc or
74 : : * is pointing partway through a palloc'd chunk. The maxlen field is set
75 : : * to 0. A read-only StringInfo cannot be appended to using any of the
76 : : * appendStringInfo functions or reset with resetStringInfo(). The given
77 : : * buffer can optionally omit the trailing NUL.
78 : : *
79 : : * StringInfoData string;
80 : : * initStringInfoFromString(&string, palloced_buf, len);
81 : : * The StringInfoData's data field is set to point directly to the given
82 : : * buffer and the StringInfoData's len is set to the given len. This
83 : : * method of initialization is useful when the buffer already exists.
84 : : * StringInfos initialized this way can be appended to using the
85 : : * appendStringInfo functions and reset with resetStringInfo(). The
86 : : * given buffer must be NUL-terminated. The palloc'd buffer is assumed
87 : : * to be len + 1 in size.
88 : : *
89 : : * To destroy a StringInfo, pfree() the data buffer, and then pfree() the
90 : : * StringInfoData if it was palloc'd. For StringInfos created with
91 : : * makeStringInfo(), destroyStringInfo() is provided for this purpose.
92 : : * However, if the StringInfo was initialized using initReadOnlyStringInfo()
93 : : * then the caller will need to consider if it is safe to pfree the data
94 : : * buffer.
95 : : *
96 : : * NOTE: some routines build up a string using StringInfo, and then
97 : : * release the StringInfoData but return the data string itself to their
98 : : * caller. At that point the data string looks like a plain palloc'd
99 : : * string.
100 : : *-------------------------
101 : : */
102 : :
103 : : /*------------------------
104 : : * makeStringInfo
105 : : * Create an empty 'StringInfoData' & return a pointer to it.
106 : : */
107 : : extern StringInfo makeStringInfo(void);
108 : :
109 : : /*------------------------
110 : : * initStringInfo
111 : : * Initialize a StringInfoData struct (with previously undefined contents)
112 : : * to describe an empty string.
113 : : */
114 : : extern void initStringInfo(StringInfo str);
115 : :
116 : : /*------------------------
117 : : * initReadOnlyStringInfo
118 : : * Initialize a StringInfoData struct from an existing string without copying
119 : : * the string. The caller is responsible for ensuring the given string
120 : : * remains valid as long as the StringInfoData does. Calls to this are used
121 : : * in performance critical locations where allocating a new buffer and copying
122 : : * would be too costly. Read-only StringInfoData's may not be appended to
123 : : * using any of the appendStringInfo functions or reset with
124 : : * resetStringInfo().
125 : : *
126 : : * 'data' does not need to point directly to a palloc'd chunk of memory and may
127 : : * omit the NUL termination character at data[len].
128 : : */
129 : : static inline void
171 drowley@postgresql.o 130 :GNC 380600 : initReadOnlyStringInfo(StringInfo str, char *data, int len)
131 : : {
132 : 380600 : str->data = data;
133 : 380600 : str->len = len;
134 : 380600 : str->maxlen = 0; /* read-only */
135 : 380600 : str->cursor = 0;
136 : 380600 : }
137 : :
138 : : /*------------------------
139 : : * initStringInfoFromString
140 : : * Initialize a StringInfoData struct from an existing string without copying
141 : : * the string. 'data' must be a valid palloc'd chunk of memory that can have
142 : : * repalloc() called should more space be required during a call to any of the
143 : : * appendStringInfo functions.
144 : : *
145 : : * 'data' must be NUL terminated at 'len' bytes.
146 : : */
147 : : static inline void
148 : 255370 : initStringInfoFromString(StringInfo str, char *data, int len)
149 : : {
150 [ - + ]: 255370 : Assert(data[len] == '\0');
151 : :
152 : 255370 : str->data = data;
153 : 255370 : str->len = len;
154 : 255370 : str->maxlen = len + 1;
155 : 255370 : str->cursor = 0;
156 : 255370 : }
157 : :
158 : : /*------------------------
159 : : * resetStringInfo
160 : : * Clears the current content of the StringInfo, if any. The
161 : : * StringInfo remains valid.
162 : : */
163 : : extern void resetStringInfo(StringInfo str);
164 : :
165 : : /*------------------------
166 : : * appendStringInfo
167 : : * Format text data under the control of fmt (an sprintf-style format string)
168 : : * and append it to whatever is already in str. More space is allocated
169 : : * to str if necessary. This is sort of like a combination of sprintf and
170 : : * strcat.
171 : : */
172 : : extern void appendStringInfo(StringInfo str, const char *fmt,...) pg_attribute_printf(2, 3);
173 : :
174 : : /*------------------------
175 : : * appendStringInfoVA
176 : : * Attempt to format text data under the control of fmt (an sprintf-style
177 : : * format string) and append it to whatever is already in str. If successful
178 : : * return zero; if not (because there's not enough space), return an estimate
179 : : * of the space needed, without modifying str. Typically the caller should
180 : : * pass the return value to enlargeStringInfo() before trying again; see
181 : : * appendStringInfo for standard usage pattern.
182 : : */
183 : : extern int appendStringInfoVA(StringInfo str, const char *fmt, va_list args) pg_attribute_printf(2, 0);
184 : :
185 : : /*------------------------
186 : : * appendStringInfoString
187 : : * Append a null-terminated string to str.
188 : : * Like appendStringInfo(str, "%s", s) but faster.
189 : : */
190 : : extern void appendStringInfoString(StringInfo str, const char *s);
191 : :
192 : : /*------------------------
193 : : * appendStringInfoChar
194 : : * Append a single byte to str.
195 : : * Like appendStringInfo(str, "%c", ch) but much faster.
196 : : */
197 : : extern void appendStringInfoChar(StringInfo str, char ch);
198 : :
199 : : /*------------------------
200 : : * appendStringInfoCharMacro
201 : : * As above, but a macro for even more speed where it matters.
202 : : * Caution: str argument will be evaluated multiple times.
203 : : */
204 : : #define appendStringInfoCharMacro(str,ch) \
205 : : (((str)->len + 1 >= (str)->maxlen) ? \
206 : : appendStringInfoChar(str, ch) : \
207 : : (void)((str)->data[(str)->len] = (ch), (str)->data[++(str)->len] = '\0'))
208 : :
209 : : /*------------------------
210 : : * appendStringInfoSpaces
211 : : * Append a given number of spaces to str.
212 : : */
213 : : extern void appendStringInfoSpaces(StringInfo str, int count);
214 : :
215 : : /*------------------------
216 : : * appendBinaryStringInfo
217 : : * Append arbitrary binary data to a StringInfo, allocating more space
218 : : * if necessary.
219 : : */
220 : : extern void appendBinaryStringInfo(StringInfo str,
221 : : const void *data, int datalen);
222 : :
223 : : /*------------------------
224 : : * appendBinaryStringInfoNT
225 : : * Append arbitrary binary data to a StringInfo, allocating more space
226 : : * if necessary. Does not ensure a trailing null-byte exists.
227 : : */
228 : : extern void appendBinaryStringInfoNT(StringInfo str,
229 : : const void *data, int datalen);
230 : :
231 : : /*------------------------
232 : : * enlargeStringInfo
233 : : * Make sure a StringInfo's buffer can hold at least 'needed' more bytes.
234 : : */
235 : : extern void enlargeStringInfo(StringInfo str, int needed);
236 : :
237 : : /*------------------------
238 : : * destroyStringInfo
239 : : * Frees a StringInfo and its buffer (opposite of makeStringInfo()).
240 : : */
241 : : extern void destroyStringInfo(StringInfo str);
242 : :
243 : : #endif /* STRINGINFO_H */
|