1 /***************************************************************************
2 * Copyright (C) 2009 By Duane Ellis *
3 * openocd@duaneellis.com *
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. *
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. *
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 ***************************************************************************/
29 // buflen is alway "+1" bigger then
30 // what is shown here, the +1 is for
31 // the NULL string terminator
32 #define DEFAULT_BUFSIZE 100
33 size_t maxlen
; // allocated size
34 size_t curlen
; // where we are inserting at
40 #define space_avail(pBuf) (pBuf->maxlen - pBuf->curlen)
41 #define dataend(pBuf) (((char *)(pBuf->buf)) + pBuf->curlen)
44 membuf_len(struct membuf
*pBuf
)
50 membuf_datapointer(struct membuf
*pBuf
)
52 return ((void *)(pBuf
->buf
));
56 membuf_strtok(struct membuf
*pBuf
, const char *sep
, void **pLast
)
59 pBuf
->_strtoklast
= NULL
;
61 // this should be "strtok_r()" but windows lacks */
62 return strtok(((char *)(pBuf
->buf
)), sep
);
65 pBuf
= *((struct membuf
**)(pLast
));
66 // this should be "strtok_r()" but windows lacks */
67 return strtok( NULL
, sep
);
76 // by default - parameters are zero.
79 pBuf
= calloc(1, sizeof(*pBuf
));
81 // we *ALWAYS* allocate +1 for null terminator.
82 pBuf
->buf
= calloc(DEFAULT_BUFSIZE
+ 1, sizeof(char));
83 if (pBuf
->buf
== NULL
) {
87 pBuf
->maxlen
= DEFAULT_BUFSIZE
;
95 membuf_grow(struct membuf
*pBuf
, int n
)
100 // this is a *SIGNED* value
101 newsize
= ((int)(pBuf
->maxlen
)) + n
;
103 // do not go negative, or too small
104 if (newsize
< DEFAULT_BUFSIZE
) {
105 newsize
= DEFAULT_BUFSIZE
;
108 // always alloc +1 for the null terminator
109 vp
= realloc(pBuf
->buf
, newsize
+ 1);
112 pBuf
->maxlen
= newsize
;
120 void membuf_reset(struct membuf
*pBuf
)
126 void membuf_delete(struct membuf
*pBuf
)
130 // wack data so it cannot be reused
131 memset(pBuf
->buf
,0,pBuf
->maxlen
);
134 // wack dat so it cannot be reused
135 memset(pBuf
,0,sizeof(pBuf
));
141 membuf_sprintf(struct membuf
*pBuf
, const char *fmt
, ...)
146 r
= membuf_vsprintf(pBuf
, fmt
, ap
);
152 membuf_vsprintf(struct membuf
*pBuf
, const char *fmt
, va_list ap
)
161 sa
= space_avail(pBuf
);
164 r
= vsnprintf(dataend(pBuf
),
168 if ((r
> 0) && (((size_t)(r
)) < sa
)) {
170 pBuf
->curlen
+= ((size_t)(r
));
171 // remember: We always alloc'ed +1
172 // so this does not overflow
173 ((char *)(pBuf
->buf
))[ pBuf
->curlen
] = 0;
180 // Option(A) format error
181 // Option(B) glibc2.0 bug
183 r
= (4 * DEFAULT_BUFSIZE
);
186 // don't do this again
192 pBuf
= membuf_grow(pBuf
, r
);
203 membuf_strcat(struct membuf
*pBuf
, const char *pStr
)
205 return membuf_append(pBuf
, pStr
, strlen(pStr
));
209 membuf_append(struct membuf
*pBuf
, const void *pData
, size_t len
)
214 // how much room is there?
215 sa
= space_avail(pBuf
);
219 // if not, how much do we need?
220 r
= ((int)(sa
- len
));
222 pBuf
= membuf_grow(pBuf
, r
);
229 memcpy(dataend(pBuf
),