diff lib/obstack_printf.c @ 10205:3384541effec

Add obstack-printf and obstack-printf-posix modules. * modules/obstack-printf: New file. * modules/obstack-printf-posix: Likewise. * MODULES.html.sh (Misc): Mention them. * doc/glibc-functions/obstack_printf.texi (obstack_printf): Likewise. * doc/glibc-functions/obstack_vprintf.texi (obstack_vprintf): Likewise. * modules/stdio (Makefile.am): Accomodate new modules. * m4/stdio_h.m4 (gl_STDIO_H_DEFAULTS): Likewise. * lib/stdio.in.h (rpl_obstack_printf, rpl_obstack_vprintf): Declare. * lib/obstack_printf.c (obstack_printf, obstack_vprintf): New functions. * m4/obstack-printf.m4 (gl_OBSTACK_PRINTF) (gl_REPLACE_OBSTACK_PRINTF): New macros * m4/obstack-printf-posix.m4 (gl_OBSTACK_PRINTF_POSIX): Likewise. * tests/test-obstack-printf.c: New file. * modules/obstack-printf-tests: Likewise. * modules/obstack-printf-posix-tests: Likewise. Signed-off-by: Eric Blake <ebb9@byu.net>
author Eric Blake <ebb9@byu.net>
date Fri, 13 Jun 2008 06:40:53 -0600 (2008-06-13)
parents
children 927afe014a7d
line wrap: on
line diff
new file mode 100644
--- /dev/null
+++ b/lib/obstack_printf.c
@@ -0,0 +1,92 @@
+/* Formatted output to obstacks.
+   Copyright (C) 2008 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License along
+   with this program; if not, write to the Free Software Foundation,
+   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
+
+#include <config.h>
+
+/* Specification.  */
+#include <stdio.h>
+
+#include "obstack.h"
+#include "vasnprintf.h"
+
+#include <errno.h>
+#include <stdarg.h>
+#include <stdlib.h>
+
+/* Grow an obstack with formatted output.  Return the number of bytes
+   added to OBS.  No trailing nul byte is added, and the object should
+   be closed with obstack_finish before use.
+
+   Upon memory allocation error, call obstack_alloc_failed_handler.
+   Upon other error, return -1.  */
+int
+obstack_printf (struct obstack *obs, const char *format, ...)
+{
+  va_list args;
+  int result;
+
+  va_start (args, format);
+  result = obstack_vprintf (obs, format, args);
+  va_end (args);
+  return result;
+}
+
+/* Grow an obstack with formatted output.  Return the number of bytes
+   added to OBS.  No trailing nul byte is added, and the object should
+   be closed with obstack_finish before use.
+
+   Upon memory allocation error, call obstack_alloc_failed_handler.
+   Upon other error, return -1.  */
+int
+obstack_vprintf (struct obstack *obs, const char *format, va_list args)
+{
+  /* If we are close to the end of the current obstack chunk, use a
+     stack-allocated buffer and copy, to reduce the likelihood of a
+     small-size malloc.  Otherwise, print directly into the
+     obstack.  */
+  const size_t cutoff = 1024;
+  char buf[cutoff];
+  char *base = obstack_next_free (obs);
+  size_t len = obstack_room (obs);
+  char *str;
+
+  if (len < cutoff)
+    {
+      base = buf;
+      len = cutoff;
+    }
+  str = vasnprintf (base, &len, format, args);
+  if (!str)
+    {
+      if (errno == ENOMEM)
+	obstack_alloc_failed_handler ();
+      return -1;
+    }
+  if (str == base && str != buf)
+    /* The output was already computed in place, but we need to
+       account for its size.  */
+    obstack_blank_fast (obs, len);
+  else
+    {
+      /* The output exceeded available obstack space or we used buf;
+	 copy the resulting string.  */
+      obstack_grow (obs, str, len);
+      if (str != buf)
+	free (str);
+    }
+  return len;
+}