Remove whitespace that occurs after '('.
[fw/openocd] / src / helper / membuf.c
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
21 #include <stdio.h>
22 #include <stdarg.h>
23 #include <malloc.h>
24 #include <string.h>
25
26 #include "membuf.h"
27
28 struct membuf {
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
35     char *_strtoklast;
36     void *buf;
37 };
38
39
40 #define space_avail(pBuf )  (pBuf->maxlen - pBuf->curlen)
41 #define dataend(pBuf )      (((char *)(pBuf->buf)) + pBuf->curlen )
42
43 size_t 
44 membuf_len(struct membuf *pBuf )
45 {
46     return pBuf->curlen;
47 }
48
49 const void *
50 membuf_datapointer(struct membuf *pBuf )
51 {
52     return ((void *)(pBuf->buf));
53 }
54
55 const char *
56 membuf_strtok(struct membuf *pBuf, const char *sep, void **pLast )
57 {
58     if (pBuf ){
59         pBuf->_strtoklast = NULL;
60         *pLast = pBuf;
61         return strtok_r(((char *)(pBuf->buf)), sep, &(pBuf->_strtoklast) );
62     } else {
63         // recover our pBuf
64         pBuf = *((struct membuf **)(pLast));
65         return strtok_r(NULL, sep, &(pBuf->_strtoklast) );
66     }
67 }
68         
69
70
71 struct membuf *
72 membuf_new(void)
73 {
74     // by default - parameters are zero.
75     struct membuf *pBuf;
76
77     pBuf = calloc(1, sizeof(*pBuf) );
78     if (pBuf ){
79         // we *ALWAYS* allocate +1 for null terminator.
80         pBuf->buf = calloc(DEFAULT_BUFSIZE + 1, sizeof(char));
81         if (pBuf->buf == NULL ){
82             free(pBuf);
83             pBuf = NULL;
84         } else {
85             pBuf->maxlen = DEFAULT_BUFSIZE;
86         }
87     }
88     return pBuf;
89 }
90
91
92 struct membuf *
93 membuf_grow(struct membuf *pBuf, int n )
94 {
95     void *vp;
96     signed int newsize;
97
98     // this is a *SIGNED* value
99     newsize = ((int)(pBuf->maxlen)) + n;
100
101     // do not go negative, or too small
102     if (newsize < DEFAULT_BUFSIZE ){
103         newsize = DEFAULT_BUFSIZE;
104     }
105
106     // always alloc +1 for the null terminator
107     vp = realloc(pBuf->buf, newsize + 1 );
108     if (vp ){
109         pBuf->buf    = vp;
110         pBuf->maxlen = newsize;
111         return pBuf;
112     } else {
113         return NULL;
114     }
115 }
116
117
118 void membuf_reset(struct membuf *pBuf )
119 {
120     pBuf->curlen = 0;
121 }
122
123
124 void membuf_delete(struct membuf *pBuf )
125 {
126     if (pBuf ){
127         if (pBuf->buf){
128             // wack data so it cannot be reused
129             memset(pBuf->buf,0,pBuf->maxlen);
130             free(pBuf->buf);
131         }
132         // wack dat so it cannot be reused
133         memset(pBuf,0,sizeof(pBuf));
134         free(pBuf);
135     }
136 }
137
138 int
139 membuf_sprintf(struct membuf *pBuf , const char *fmt, ... )
140 {
141     int r;
142     va_list ap;
143     va_start(ap, fmt );
144     r = membuf_vsprintf(pBuf, fmt, ap );
145     va_end(ap);
146     return r;
147 }
148
149 int
150 membuf_vsprintf(struct membuf *pBuf, const char *fmt, va_list ap )
151 {
152     int r;
153     size_t sa;
154     int grew;
155
156
157     grew = 0;
158     for (;;) {
159         sa = space_avail(pBuf);
160
161         // do work
162         r = vsnprintf(dataend(pBuf ),
163                        sa,
164                        fmt, 
165                        ap );
166         if ((r > 0) && (((size_t)(r)) < sa) ){
167             // Success!
168             pBuf->curlen += ((size_t)(r));
169             // remember: We always alloc'ed +1
170             // so this does not overflow
171             ((char *)(pBuf->buf))[ pBuf->curlen ] = 0;
172             r = 0;
173             break;
174         }
175
176         // failure
177         if (r < 0 ){
178             // Option(A) format error
179             // Option(B) glibc2.0 bug
180             // assume (B).
181             r = (4 * DEFAULT_BUFSIZE);
182         }
183
184         // don't do this again
185         if (grew ){
186             r = -1;
187             break;
188         }
189         grew = 1;
190         pBuf = membuf_grow(pBuf, r );
191         if (pBuf == NULL){
192             // grow failed
193             r = -1;
194             break;
195         }
196     }
197     return r;
198 }
199
200 struct membuf *
201 membuf_strcat(struct membuf *pBuf, const char *pStr )
202 {
203     return membuf_append(pBuf, pStr, strlen(pStr ) );
204 }
205
206 struct membuf *
207 membuf_append(struct membuf *pBuf, const void *pData, size_t len )
208 {
209     size_t sa;
210     int r;
211
212     // how much room is there?
213     sa = space_avail(pBuf );
214
215     // will it fit?
216     if (sa < len ){
217         // if not, how much do we need?
218         r = ((int)(sa - len));
219         // do the grow.
220         pBuf = membuf_grow(pBuf, r );
221         // failed?
222         if (pBuf == NULL){
223             return pBuf;
224         }
225     }
226     // append
227     memcpy(dataend(pBuf),
228             pData,
229             len );
230     pBuf->curlen += len;
231     return pBuf;
232 }
233
234
235
236
237
238