asprintf.c 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  1. /*!
  2. * \file lib/gis/asprintf.c
  3. *
  4. * \brief GIS Library - GRASS implementation of asprintf().
  5. *
  6. * Eric G. Miller - Thu, 2 May 2002 17:51:54 -0700
  7. *
  8. * Rewritten by Glynn Clements, Sat, 6 Feb 2010
  9. * Assumes that vsnprintf() is available
  10. *
  11. * (C) 2002-2014 by the GRASS Development Team
  12. * (C) 2010 by Glynn Clements
  13. *
  14. * This program is free software under the GNU General Public License
  15. * (>=v2). Read the file COPYING that comes with GRASS for details.
  16. */
  17. #define _GNU_SOURCE /* enable asprintf */
  18. #include <stdio.h>
  19. #include <stdarg.h>
  20. #include <string.h>
  21. #include <grass/gis.h>
  22. #ifndef G_asprintf
  23. /**
  24. * \brief Safe replacement for <i>asprintf()</i>.
  25. *
  26. * Allocate a string large enough to hold the new output, including the
  27. * terminating NULL, and return the number of characters printed. The
  28. * pointer out is set to the output string and should be passed to
  29. * <i>G_free()</i> to release the allocated storage when it is no longer
  30. * needed.
  31. *
  32. * \param[out] out
  33. * \param[in] fmt
  34. * \param ap
  35. * \return number of bytes written
  36. */
  37. int G_vasprintf(char **out, const char *fmt, va_list ap)
  38. {
  39. #ifdef HAVE_ASPRINTF
  40. return vasprintf(out, fmt, ap);
  41. #else
  42. size_t size = strlen(fmt) + 50;
  43. char *buf = G_malloc(size);
  44. int count;
  45. for (;;) {
  46. /* BUG: according to man vsnprintf,
  47. * va_start() should be called immediately before vsnprintf(),
  48. * and va_end() immediately after vsnprintf()
  49. * otherwise there will be memory corruption */
  50. count = vsnprintf(buf, size, fmt, ap);
  51. if (count >= 0 && count < size)
  52. break;
  53. size *= 2;
  54. buf = G_realloc(buf, size);
  55. }
  56. buf = G_realloc(buf, count + 1);
  57. *out = buf;
  58. return count;
  59. #endif /* HAVE_ASPRINTF */
  60. }
  61. int G_asprintf(char **out, const char *fmt, ...)
  62. {
  63. va_list ap;
  64. int count;
  65. va_start(ap, fmt);
  66. count = G_vasprintf(out, fmt, ap);
  67. va_end(ap);
  68. return count;
  69. }
  70. #endif /* G_asprintf */
  71. /**
  72. * \brief Reallocating version of <i>asprintf()</i>.
  73. *
  74. * Reallocate a string large enough to hold the output, including the
  75. * terminating NULL, and return the number of characters printed.
  76. * Contrary to <i>G_asprintf()</i>, any existing buffer pointed to by
  77. * out of size osize is used to hold the output and enlarged if
  78. * necessary. This is useful when <i>G_rasprintf</i> is called many
  79. * times in a loop.
  80. *
  81. * \param[out] out
  82. * \param[out] osize
  83. * \param[in] fmt
  84. * \param ap
  85. * \return number of bytes written
  86. */
  87. int G_rasprintf(char **out, size_t *size, const char *fmt, ...)
  88. {
  89. va_list ap;
  90. int count;
  91. char *buf = *out;
  92. size_t osize = *size;
  93. if (osize < strlen(fmt) + 50) {
  94. osize = strlen(fmt) + 50;
  95. buf = G_realloc(buf, osize);
  96. }
  97. for (;;) {
  98. va_start(ap, fmt);
  99. count = vsnprintf(buf, osize, fmt, ap);
  100. va_end(ap);
  101. if (count >= 0 && count < osize)
  102. break;
  103. if (count > -1)
  104. osize = count + 1;
  105. else
  106. osize *= 2;
  107. buf = G_realloc(buf, osize);
  108. }
  109. *out = buf;
  110. *size = osize;
  111. return count;
  112. }