| 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 |  | 
|---|