1 | /*------------------------------------------------------------------------- |
2 | * |
3 | * pqexpbuffer.h |
4 | * Declarations/definitions for "PQExpBuffer" functions. |
5 | * |
6 | * PQExpBuffer provides an indefinitely-extensible string data type. |
7 | * It can be used to buffer either ordinary C strings (null-terminated text) |
8 | * or arbitrary binary data. All storage is allocated with malloc(). |
9 | * |
10 | * This module is essentially the same as the backend's StringInfo data type, |
11 | * but it is intended for use in frontend libpq and client applications. |
12 | * Thus, it does not rely on palloc() nor elog(). |
13 | * |
14 | * It does rely on vsnprintf(); if configure finds that libc doesn't provide |
15 | * a usable vsnprintf(), then a copy of our own implementation of it will |
16 | * be linked into libpq. |
17 | * |
18 | * Portions Copyright (c) 1996-2019, PostgreSQL Global Development Group |
19 | * Portions Copyright (c) 1994, Regents of the University of California |
20 | * |
21 | * src/interfaces/libpq/pqexpbuffer.h |
22 | * |
23 | *------------------------------------------------------------------------- |
24 | */ |
25 | #ifndef PQEXPBUFFER_H |
26 | #define PQEXPBUFFER_H |
27 | |
28 | /*------------------------- |
29 | * PQExpBufferData holds information about an extensible string. |
30 | * data is the current buffer for the string (allocated with malloc). |
31 | * len is the current string length. There is guaranteed to be |
32 | * a terminating '\0' at data[len], although this is not very |
33 | * useful when the string holds binary data rather than text. |
34 | * maxlen is the allocated size in bytes of 'data', i.e. the maximum |
35 | * string size (including the terminating '\0' char) that we can |
36 | * currently store in 'data' without having to reallocate |
37 | * more space. We must always have maxlen > len. |
38 | * |
39 | * An exception occurs if we failed to allocate enough memory for the string |
40 | * buffer. In that case data points to a statically allocated empty string, |
41 | * and len = maxlen = 0. |
42 | *------------------------- |
43 | */ |
44 | typedef struct PQExpBufferData |
45 | { |
46 | char *data; |
47 | size_t len; |
48 | size_t maxlen; |
49 | } PQExpBufferData; |
50 | |
51 | typedef PQExpBufferData *PQExpBuffer; |
52 | |
53 | /*------------------------ |
54 | * Test for a broken (out of memory) PQExpBuffer. |
55 | * When a buffer is "broken", all operations except resetting or deleting it |
56 | * are no-ops. |
57 | *------------------------ |
58 | */ |
59 | #define PQExpBufferBroken(str) \ |
60 | ((str) == NULL || (str)->maxlen == 0) |
61 | |
62 | /*------------------------ |
63 | * Same, but for use when using a static or local PQExpBufferData struct. |
64 | * For that, a null-pointer test is useless and may draw compiler warnings. |
65 | *------------------------ |
66 | */ |
67 | #define PQExpBufferDataBroken(buf) \ |
68 | ((buf).maxlen == 0) |
69 | |
70 | /*------------------------ |
71 | * Initial size of the data buffer in a PQExpBuffer. |
72 | * NB: this must be large enough to hold error messages that might |
73 | * be returned by PQrequestCancel(). |
74 | *------------------------ |
75 | */ |
76 | #define INITIAL_EXPBUFFER_SIZE 256 |
77 | |
78 | /*------------------------ |
79 | * There are two ways to create a PQExpBuffer object initially: |
80 | * |
81 | * PQExpBuffer stringptr = createPQExpBuffer(); |
82 | * Both the PQExpBufferData and the data buffer are malloc'd. |
83 | * |
84 | * PQExpBufferData string; |
85 | * initPQExpBuffer(&string); |
86 | * The data buffer is malloc'd but the PQExpBufferData is presupplied. |
87 | * This is appropriate if the PQExpBufferData is a field of another |
88 | * struct. |
89 | *------------------------- |
90 | */ |
91 | |
92 | /*------------------------ |
93 | * createPQExpBuffer |
94 | * Create an empty 'PQExpBufferData' & return a pointer to it. |
95 | */ |
96 | extern PQExpBuffer createPQExpBuffer(void); |
97 | |
98 | /*------------------------ |
99 | * initPQExpBuffer |
100 | * Initialize a PQExpBufferData struct (with previously undefined contents) |
101 | * to describe an empty string. |
102 | */ |
103 | extern void initPQExpBuffer(PQExpBuffer str); |
104 | |
105 | /*------------------------ |
106 | * To destroy a PQExpBuffer, use either: |
107 | * |
108 | * destroyPQExpBuffer(str); |
109 | * free()s both the data buffer and the PQExpBufferData. |
110 | * This is the inverse of createPQExpBuffer(). |
111 | * |
112 | * termPQExpBuffer(str) |
113 | * free()s the data buffer but not the PQExpBufferData itself. |
114 | * This is the inverse of initPQExpBuffer(). |
115 | * |
116 | * NOTE: some routines build up a string using PQExpBuffer, and then |
117 | * release the PQExpBufferData but return the data string itself to their |
118 | * caller. At that point the data string looks like a plain malloc'd |
119 | * string. |
120 | */ |
121 | extern void destroyPQExpBuffer(PQExpBuffer str); |
122 | extern void termPQExpBuffer(PQExpBuffer str); |
123 | |
124 | /*------------------------ |
125 | * resetPQExpBuffer |
126 | * Reset a PQExpBuffer to empty |
127 | * |
128 | * Note: if possible, a "broken" PQExpBuffer is returned to normal. |
129 | */ |
130 | extern void resetPQExpBuffer(PQExpBuffer str); |
131 | |
132 | /*------------------------ |
133 | * enlargePQExpBuffer |
134 | * Make sure there is enough space for 'needed' more bytes in the buffer |
135 | * ('needed' does not include the terminating null). |
136 | * |
137 | * Returns 1 if OK, 0 if failed to enlarge buffer. (In the latter case |
138 | * the buffer is left in "broken" state.) |
139 | */ |
140 | extern int enlargePQExpBuffer(PQExpBuffer str, size_t needed); |
141 | |
142 | /*------------------------ |
143 | * printfPQExpBuffer |
144 | * Format text data under the control of fmt (an sprintf-like format string) |
145 | * and insert it into str. More space is allocated to str if necessary. |
146 | * This is a convenience routine that does the same thing as |
147 | * resetPQExpBuffer() followed by appendPQExpBuffer(). |
148 | */ |
149 | extern void printfPQExpBuffer(PQExpBuffer str, const char *fmt,...) pg_attribute_printf(2, 3); |
150 | |
151 | /*------------------------ |
152 | * appendPQExpBuffer |
153 | * Format text data under the control of fmt (an sprintf-like format string) |
154 | * and append it to whatever is already in str. More space is allocated |
155 | * to str if necessary. This is sort of like a combination of sprintf and |
156 | * strcat. |
157 | */ |
158 | extern void appendPQExpBuffer(PQExpBuffer str, const char *fmt,...) pg_attribute_printf(2, 3); |
159 | |
160 | /*------------------------ |
161 | * appendPQExpBufferStr |
162 | * Append the given string to a PQExpBuffer, allocating more space |
163 | * if necessary. |
164 | */ |
165 | extern void appendPQExpBufferStr(PQExpBuffer str, const char *data); |
166 | |
167 | /*------------------------ |
168 | * appendPQExpBufferChar |
169 | * Append a single byte to str. |
170 | * Like appendPQExpBuffer(str, "%c", ch) but much faster. |
171 | */ |
172 | extern void appendPQExpBufferChar(PQExpBuffer str, char ch); |
173 | |
174 | /*------------------------ |
175 | * appendBinaryPQExpBuffer |
176 | * Append arbitrary binary data to a PQExpBuffer, allocating more space |
177 | * if necessary. |
178 | */ |
179 | extern void appendBinaryPQExpBuffer(PQExpBuffer str, |
180 | const char *data, size_t datalen); |
181 | |
182 | #endif /* PQEXPBUFFER_H */ |
183 | |