vasprintf.c 1.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778
  1. /* Copyright (C) 2004 Manuel Novoa III <mjn3@codepoet.org>
  2. *
  3. * GNU Library General Public License (LGPL) version 2 or later.
  4. *
  5. * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details.
  6. */
  7. #include <features.h>
  8. #ifdef __USE_GNU
  9. #include "_stdio.h"
  10. #include <stdarg.h>
  11. #include <bits/uClibc_va_copy.h>
  12. #ifndef __STDIO_HAS_VSNPRINTF
  13. #warning Skipping vasprintf since no vsnprintf!
  14. #else
  15. int vasprintf(char **__restrict buf, const char * __restrict format,
  16. va_list arg)
  17. {
  18. #ifdef __UCLIBC_HAS_GLIBC_CUSTOM_STREAMS__
  19. FILE *f;
  20. size_t size;
  21. int rv = -1;
  22. *buf = NULL;
  23. if ((f = open_memstream(buf, &size)) != NULL) {
  24. rv = vfprintf(f, format, arg);
  25. fclose(f);
  26. if (rv < 0) {
  27. free(*buf);
  28. *buf = NULL;
  29. } else {
  30. *buf = realloc(*buf, rv + 1);
  31. }
  32. }
  33. assert(rv >= -1);
  34. return rv;
  35. #else /* __UCLIBC_HAS_GLIBC_CUSTOM_STREAMS__ */
  36. /* This implementation actually calls the printf machinery twice, but
  37. * only does one malloc. This can be a problem though when custom printf
  38. * specs or the %m specifier are involved because the results of the
  39. * second call might be different from the first. */
  40. va_list arg2;
  41. int rv;
  42. va_copy(arg2, arg);
  43. rv = vsnprintf(NULL, 0, format, arg2);
  44. va_end(arg2);
  45. *buf = NULL;
  46. if (rv >= 0) {
  47. if ((*buf = malloc(++rv)) != NULL) {
  48. if ((rv = vsnprintf(*buf, rv, format, arg)) < 0) {
  49. free(*buf);
  50. *buf = NULL;
  51. }
  52. }
  53. }
  54. assert(rv >= -1);
  55. return rv;
  56. #endif /* __UCLIBC_HAS_GLIBC_CUSTOM_STREAMS__ */
  57. }
  58. libc_hidden_def(vasprintf)
  59. #endif
  60. #endif