asprintf.c 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133
  1. /**
  2. * \file 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) 2001-2008 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 <grass/config.h>
  19. #include <stdio.h>
  20. #include <stdarg.h>
  21. #include <string.h>
  22. #include <grass/gis.h>
  23. #ifndef G_asprintf
  24. /**
  25. * \brief Safe replacement for <i>asprintf()</i>.
  26. *
  27. * Allocate a string large enough to hold the new output, including the
  28. * terminating NULL, and return the number of characters printed. The
  29. * pointer out is set to the output string and should be passed to
  30. * <i>G_free()</i> to release the allocated storage when it is no longer
  31. * needed.
  32. *
  33. * \param[out] out
  34. * \param[in] fmt
  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. count = vsnprintf(buf, size, fmt, ap);
  47. if (count >= 0 && count < size)
  48. break;
  49. size *= 2;
  50. buf = G_realloc(buf, size);
  51. }
  52. buf = G_realloc(buf, count + 1);
  53. *out = buf;
  54. return count;
  55. #endif /* HAVE_ASPRINTF */
  56. }
  57. int G_asprintf(char **out, const char *fmt, ...)
  58. {
  59. va_list ap;
  60. int count;
  61. va_start(ap, fmt);
  62. count = G_vasprintf(out, fmt, ap);
  63. va_end(ap);
  64. return count;
  65. }
  66. #endif /* G_asprintf */
  67. /**
  68. * \brief Reallocating version of <i>asprintf()</i>.
  69. *
  70. * Reallocate a string large enough to hold the output, including the
  71. * terminating NULL, and return the number of characters printed.
  72. * Contrary to <i>G_asprintf()</i>, any existing buffer pointed to by
  73. * out of size osize is used to hold the output and enlarged if
  74. * necessary. This is usefull when <i>G_rasprintf</i> is called many
  75. * times in a loop.
  76. *
  77. * \param[out] out
  78. * \param[out] size
  79. * \param[in] fmt
  80. * \return number of bytes written
  81. */
  82. int G_vsnprintf(char **out, size_t *osize, const char *fmt, va_list ap)
  83. {
  84. char *buf = *out;
  85. int count;
  86. size_t size = *osize;
  87. if (size < strlen(fmt) + 50) {
  88. size = strlen(fmt) + 50;
  89. buf = G_realloc(buf, size);
  90. }
  91. for (;;) {
  92. count = vsnprintf(buf, size, fmt, ap);
  93. if (count >= 0 && count < size)
  94. break;
  95. size *= 2;
  96. buf = G_realloc(buf, size);
  97. }
  98. buf = G_realloc(buf, count + 1);
  99. *out = buf;
  100. *osize = size;
  101. return count;
  102. }
  103. int G_rasprintf(char **out, size_t *size, const char *fmt, ...)
  104. {
  105. va_list ap;
  106. int count;
  107. va_start(ap, fmt);
  108. count = G_vsnprintf(out, size, fmt, ap);
  109. va_end(ap);
  110. return count;
  111. }