You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

241 lines
5.3 KiB

  1. /***************************************************************************
  2. * Copyright (C) 2009 By Duane Ellis *
  3. * openocd@duaneellis.com *
  4. * *
  5. * This program is free software; you can redistribute it and/or modify *
  6. * it under the terms of the GNU General Public License as published by *
  7. * the Free Software Foundation; either version 2 of the License, or *
  8. * (at your option) any later version. *
  9. * *
  10. * This program is distributed in the hope that it will be useful, *
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of *
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
  13. * GNU General Public License for more details. *
  14. * *
  15. * You should have received a copy of the GNU General Public License *
  16. * along with this program; if not, write to the *
  17. * Free Software Foundation, Inc., *
  18. * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
  19. ***************************************************************************/
  20. #include <stdio.h>
  21. #include <stdarg.h>
  22. #include <stdlib.h>
  23. #include <string.h>
  24. #include "membuf.h"
  25. struct membuf {
  26. // buflen is alway "+1" bigger then
  27. // what is shown here, the +1 is for
  28. // the NULL string terminator
  29. #define DEFAULT_BUFSIZE 100
  30. size_t maxlen; // allocated size
  31. size_t curlen; // where we are inserting at
  32. char *_strtoklast;
  33. void *buf;
  34. };
  35. #define space_avail(pBuf) (pBuf->maxlen - pBuf->curlen)
  36. #define dataend(pBuf) (((char *)(pBuf->buf)) + pBuf->curlen)
  37. size_t
  38. membuf_len(struct membuf *pBuf)
  39. {
  40. return pBuf->curlen;
  41. }
  42. const void *
  43. membuf_datapointer(struct membuf *pBuf)
  44. {
  45. return ((void *)(pBuf->buf));
  46. }
  47. const char *
  48. membuf_strtok(struct membuf *pBuf, const char *sep, void **pLast)
  49. {
  50. if (pBuf) {
  51. pBuf->_strtoklast = NULL;
  52. *pLast = pBuf;
  53. // this should be "strtok_r()" but windows lacks */
  54. return strtok(((char *)(pBuf->buf)), sep);
  55. } else {
  56. // recover our pBuf
  57. pBuf = *((struct membuf **)(pLast));
  58. // this should be "strtok_r()" but windows lacks */
  59. return strtok( NULL, sep);
  60. }
  61. }
  62. struct membuf *
  63. membuf_new(void)
  64. {
  65. // by default - parameters are zero.
  66. struct membuf *pBuf;
  67. pBuf = calloc(1, sizeof(*pBuf));
  68. if (pBuf) {
  69. // we *ALWAYS* allocate +1 for null terminator.
  70. pBuf->buf = calloc(DEFAULT_BUFSIZE + 1, sizeof(char));
  71. if (pBuf->buf == NULL) {
  72. free(pBuf);
  73. pBuf = NULL;
  74. } else {
  75. pBuf->maxlen = DEFAULT_BUFSIZE;
  76. }
  77. }
  78. return pBuf;
  79. }
  80. struct membuf *
  81. membuf_grow(struct membuf *pBuf, int n)
  82. {
  83. void *vp;
  84. signed int newsize;
  85. // this is a *SIGNED* value
  86. newsize = ((int)(pBuf->maxlen)) + n;
  87. // do not go negative, or too small
  88. if (newsize < DEFAULT_BUFSIZE) {
  89. newsize = DEFAULT_BUFSIZE;
  90. }
  91. // always alloc +1 for the null terminator
  92. vp = realloc(pBuf->buf, newsize + 1);
  93. if (vp) {
  94. pBuf->buf = vp;
  95. pBuf->maxlen = newsize;
  96. return pBuf;
  97. } else {
  98. return NULL;
  99. }
  100. }
  101. void membuf_reset(struct membuf *pBuf)
  102. {
  103. pBuf->curlen = 0;
  104. }
  105. void membuf_delete(struct membuf *pBuf)
  106. {
  107. if (pBuf) {
  108. if (pBuf->buf) {
  109. // wack data so it cannot be reused
  110. memset(pBuf->buf,0,pBuf->maxlen);
  111. free(pBuf->buf);
  112. }
  113. // wack dat so it cannot be reused
  114. memset(pBuf,0,sizeof(pBuf));
  115. free(pBuf);
  116. }
  117. }
  118. int
  119. membuf_sprintf(struct membuf *pBuf , const char *fmt, ...)
  120. {
  121. int r;
  122. va_list ap;
  123. va_start(ap, fmt);
  124. r = membuf_vsprintf(pBuf, fmt, ap);
  125. va_end(ap);
  126. return r;
  127. }
  128. int
  129. membuf_vsprintf(struct membuf *pBuf, const char *fmt, va_list ap)
  130. {
  131. int r;
  132. size_t sa;
  133. int grew;
  134. grew = 0;
  135. for (;;) {
  136. sa = space_avail(pBuf);
  137. // do work
  138. r = vsnprintf(dataend(pBuf),
  139. sa,
  140. fmt,
  141. ap);
  142. if ((r > 0) && (((size_t)(r)) < sa)) {
  143. // Success!
  144. pBuf->curlen += ((size_t)(r));
  145. // remember: We always alloc'ed +1
  146. // so this does not overflow
  147. ((char *)(pBuf->buf))[ pBuf->curlen ] = 0;
  148. r = 0;
  149. break;
  150. }
  151. // failure
  152. if (r < 0) {
  153. // Option(A) format error
  154. // Option(B) glibc2.0 bug
  155. // assume (B).
  156. r = (4 * DEFAULT_BUFSIZE);
  157. }
  158. // don't do this again
  159. if (grew) {
  160. r = -1;
  161. break;
  162. }
  163. grew = 1;
  164. pBuf = membuf_grow(pBuf, r);
  165. if (pBuf == NULL) {
  166. // grow failed
  167. r = -1;
  168. break;
  169. }
  170. }
  171. return r;
  172. }
  173. struct membuf *
  174. membuf_strcat(struct membuf *pBuf, const char *pStr)
  175. {
  176. return membuf_append(pBuf, pStr, strlen(pStr));
  177. }
  178. struct membuf *
  179. membuf_append(struct membuf *pBuf, const void *pData, size_t len)
  180. {
  181. size_t sa;
  182. int r;
  183. // how much room is there?
  184. sa = space_avail(pBuf);
  185. // will it fit?
  186. if (sa < len) {
  187. // if not, how much do we need?
  188. r = ((int)(sa - len));
  189. // do the grow.
  190. pBuf = membuf_grow(pBuf, r);
  191. // failed?
  192. if (pBuf == NULL) {
  193. return pBuf;
  194. }
  195. }
  196. // append
  197. memcpy(dataend(pBuf),
  198. pData,
  199. len);
  200. pBuf->curlen += len;
  201. return pBuf;
  202. }