88 *
99 * This module is essentially the same as the backend's StringInfo data type,
1010 * but it is intended for use in frontend libpq and client applications.
11- * Thus, it does not rely on palloc(), elog(), nor vsnprintf().
11+ * Thus, it does not rely on palloc() nor elog().
12+ *
13+ * It does rely on vsnprintf(); if configure finds that libc doesn't provide
14+ * a usable vsnprintf(), then a copy of our own implementation of it will
15+ * be linked into libpq.
1216 *
1317 * Copyright (c) 1994, Regents of the University of California
1418 *
15- * $Header: /cvsroot/pgsql/src/interfaces/libpq/pqexpbuffer.c,v 1.1 1999/08/31 01:37:37 tgl Exp $
19+ * $Header: /cvsroot/pgsql/src/interfaces/libpq/pqexpbuffer.c,v 1.2 2000/01/17 02:59:46 tgl Exp $
1620 *
1721 *-------------------------------------------------------------------------
1822 */
@@ -148,27 +152,47 @@ enlargePQExpBuffer(PQExpBuffer str, int needed)
148152 * and insert it into str. More space is allocated to str if necessary.
149153 * This is a convenience routine that does the same thing as
150154 * resetPQExpBuffer() followed by appendPQExpBuffer().
151- *
152- * CAUTION: the frontend version of this routine WILL FAIL if the result of
153- * the sprintf formatting operation exceeds 1KB of data (but the size of the
154- * pre-existing string in the buffer doesn't matter). We could make it
155- * support larger strings, but that requires vsnprintf() which is not
156- * universally available. Currently there is no need for long strings to be
157- * formatted in the frontend. We could support it, if necessary, by
158- * conditionally including a vsnprintf emulation.
159155 */
160156void
161157printfPQExpBuffer (PQExpBuffer str ,const char * fmt ,...)
162158{
163159va_list args ;
164- char buffer [1024 ];
165-
166- va_start (args ,fmt );
167- vsprintf (buffer ,fmt ,args );
168- va_end (args );
160+ int avail ,
161+ nprinted ;
169162
170163resetPQExpBuffer (str );
171- appendPQExpBufferStr (str ,buffer );
164+
165+ for (;;)
166+ {
167+ /*----------
168+ * Try to format the given string into the available space;
169+ * but if there's hardly any space, don't bother trying,
170+ * just fall through to enlarge the buffer first.
171+ *----------
172+ */
173+ avail = str -> maxlen - str -> len - 1 ;
174+ if (avail > 16 )
175+ {
176+ va_start (args ,fmt );
177+ nprinted = vsnprintf (str -> data + str -> len ,avail ,
178+ fmt ,args );
179+ va_end (args );
180+ /*
181+ * Note: some versions of vsnprintf return the number of chars
182+ * actually stored, but at least one returns -1 on failure.
183+ * Be conservative about believing whether the print worked.
184+ */
185+ if (nprinted >=0 && nprinted < avail - 1 )
186+ {
187+ /* Success. Note nprinted does not include trailing null. */
188+ str -> len += nprinted ;
189+ break ;
190+ }
191+ }
192+ /* Double the buffer size and try again. */
193+ if (!enlargePQExpBuffer (str ,str -> maxlen ))
194+ return ;/* oops, out of memory */
195+ }
172196}
173197
174198/*------------------------
@@ -178,26 +202,45 @@ printfPQExpBuffer(PQExpBuffer str, const char *fmt,...)
178202 * and append it to whatever is already in str. More space is allocated
179203 * to str if necessary. This is sort of like a combination of sprintf and
180204 * strcat.
181- *
182- * CAUTION: the frontend version of this routine WILL FAIL if the result of
183- * the sprintf formatting operation exceeds 1KB of data (but the size of the
184- * pre-existing string in the buffer doesn't matter). We could make it
185- * support larger strings, but that requires vsnprintf() which is not
186- * universally available. Currently there is no need for long strings to be
187- * formatted in the frontend. We could support it, if necessary, by
188- * conditionally including a vsnprintf emulation.
189205 */
190206void
191207appendPQExpBuffer (PQExpBuffer str ,const char * fmt ,...)
192208{
193209va_list args ;
194- char buffer [1024 ];
195-
196- va_start (args ,fmt );
197- vsprintf (buffer ,fmt ,args );
198- va_end (args );
210+ int avail ,
211+ nprinted ;
199212
200- appendPQExpBufferStr (str ,buffer );
213+ for (;;)
214+ {
215+ /*----------
216+ * Try to format the given string into the available space;
217+ * but if there's hardly any space, don't bother trying,
218+ * just fall through to enlarge the buffer first.
219+ *----------
220+ */
221+ avail = str -> maxlen - str -> len - 1 ;
222+ if (avail > 16 )
223+ {
224+ va_start (args ,fmt );
225+ nprinted = vsnprintf (str -> data + str -> len ,avail ,
226+ fmt ,args );
227+ va_end (args );
228+ /*
229+ * Note: some versions of vsnprintf return the number of chars
230+ * actually stored, but at least one returns -1 on failure.
231+ * Be conservative about believing whether the print worked.
232+ */
233+ if (nprinted >=0 && nprinted < avail - 1 )
234+ {
235+ /* Success. Note nprinted does not include trailing null. */
236+ str -> len += nprinted ;
237+ break ;
238+ }
239+ }
240+ /* Double the buffer size and try again. */
241+ if (!enlargePQExpBuffer (str ,str -> maxlen ))
242+ return ;/* oops, out of memory */
243+ }
201244}
202245
203246/*------------------------