asprintf.c 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  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. * \param ap
  36. * \return number of bytes written
  37. */
  38. int G_vasprintf(char **out, const char *fmt, va_list ap)
  39. {
  40. #ifdef HAVE_ASPRINTF
  41. return vasprintf(out, fmt, ap);
  42. #else
  43. size_t size = strlen(fmt) + 50;
  44. char *buf = G_malloc(size);
  45. int count;
  46. for (;;) {
  47. count = vsnprintf(buf, size, fmt, ap);
  48. if (count >= 0 && count < size)
  49. break;
  50. size *= 2;
  51. buf = G_realloc(buf, size);
  52. }
  53. buf = G_realloc(buf, count + 1);
  54. *out = buf;
  55. return count;
  56. #endif /* HAVE_ASPRINTF */
  57. }
  58. int G_asprintf(char **out, const char *fmt, ...)
  59. {
  60. va_list ap;
  61. int count;
  62. va_start(ap, fmt);
  63. count = G_vasprintf(out, fmt, ap);
  64. va_end(ap);
  65. return count;
  66. }
  67. #endif /* G_asprintf */
  68. /**
  69. * \brief Reallocating version of <i>asprintf()</i>.
  70. *
  71. * Reallocate a string large enough to hold the output, including the
  72. * terminating NULL, and return the number of characters printed.
  73. * Contrary to <i>G_asprintf()</i>, any existing buffer pointed to by
  74. * out of size osize is used to hold the output and enlarged if
  75. * necessary. This is usefull when <i>G_rasprintf</i> is called many
  76. * times in a loop.
  77. *
  78. * \param[out] out
  79. * \param[out] osize
  80. * \param[in] fmt
  81. * \param ap
  82. * \return number of bytes written
  83. */
  84. int G_vsnprintf(char **out, size_t *osize, const char *fmt, va_list ap)
  85. {
  86. char *buf = *out;
  87. int count;
  88. size_t size = *osize;
  89. if (size < strlen(fmt) + 50) {
  90. size = strlen(fmt) + 50;
  91. buf = G_realloc(buf, size);
  92. }
  93. for (;;) {
  94. count = vsnprintf(buf, size, fmt, ap);
  95. if (count >= 0 && count < size)
  96. break;
  97. size *= 2;
  98. buf = G_realloc(buf, size);
  99. }
  100. buf = G_realloc(buf, count + 1);
  101. *out = buf;
  102. *osize = size;
  103. return count;
  104. }
  105. int G_rasprintf(char **out, size_t *size, const char *fmt, ...)
  106. {
  107. va_list ap;
  108. int count;
  109. va_start(ap, fmt);
  110. count = G_vsnprintf(out, size, fmt, ap);
  111. va_end(ap);
  112. return count;
  113. }