Mercurial > hg > dmlib
comparison src/dmgrowbuf.c @ 1697:1036b0dcccb5
Refactor DMGrowBuf so that there can be buffers that grow "backwards".
This also removes some support functions like the buffer state push/pop.
author | Matti Hamalainen <ccr@tnsp.org> |
---|---|
date | Tue, 05 Jun 2018 12:55:17 +0300 |
parents | e568535e1a96 |
children | f71cd6691e05 |
comparison
equal
deleted
inserted
replaced
1696:cf0fddd4bf52 | 1697:1036b0dcccb5 |
---|---|
43 buf->size = initial; | 43 buf->size = initial; |
44 buf->mingrow = mingrow; | 44 buf->mingrow = mingrow; |
45 buf->allocated = FALSE; | 45 buf->allocated = FALSE; |
46 | 46 |
47 // Allocate the data | 47 // Allocate the data |
48 if ((buf->adata = buf->data = dmMalloc0(initial)) == NULL) | 48 if ((buf->data = dmMalloc0(initial)) == NULL) |
49 return DMERR_MALLOC; | 49 return DMERR_MALLOC; |
50 | 50 |
51 return DMERR_OK; | 51 return DMERR_OK; |
52 } | 52 } |
53 | 53 |
83 { | 83 { |
84 DM_DBG("dmGrowBufFree(%p)\n", buf); | 84 DM_DBG("dmGrowBufFree(%p)\n", buf); |
85 if (buf != NULL) | 85 if (buf != NULL) |
86 { | 86 { |
87 DM_DBG( | 87 DM_DBG( |
88 " buf->adata = %p\n" | |
89 " buf->data = %p\n" | 88 " buf->data = %p\n" |
90 " buf->allocated = %s\n", | 89 " buf->allocated = %s\n", |
91 buf->adata, buf->data, buf->allocated ? "YES" : "NO"); | 90 buf->data, buf->allocated ? "YES" : "NO"); |
92 | 91 |
93 dmFreeR(&buf->adata); | 92 dmFreeR(&buf->data); |
94 buf->data = NULL; | |
95 | 93 |
96 if (buf->allocated) | 94 if (buf->allocated) |
97 dmFree(buf); | 95 dmFree(buf); |
98 } | 96 } |
99 } | 97 } |
100 | 98 |
101 | 99 |
102 void dmGrowBufPush(DMGrowBuf *buf) | |
103 { | |
104 if (buf != NULL && buf->adata != NULL) | |
105 { | |
106 DM_DBG("dmGrowBufPush(%p): size=%" DM_PRIu_SIZE_T "\n" | |
107 " nstack=%d [offs=%" DM_PRIu_SIZE_T ", len=%" DM_PRIu_SIZE_T "]\n", | |
108 buf, buf->size, buf->nstack, buf->offs, buf->len); | |
109 | |
110 buf->stack[buf->nstack].offs = buf->offs; | |
111 buf->stack[buf->nstack].len = buf->len; | |
112 buf->nstack++; | |
113 | |
114 buf->offs = buf->len; | |
115 buf->data = buf->adata + buf->offs; | |
116 buf->len = 0; | |
117 | |
118 DM_DBG( | |
119 " nstack=%d [offs=%" DM_PRIu_SIZE_T ", len=%" DM_PRIu_SIZE_T "]\n", | |
120 buf->nstack, buf->offs, buf->len); | |
121 } | |
122 else | |
123 DM_DBG("dmGrowBufPush(%p)\n", buf); | |
124 } | |
125 | |
126 | |
127 void dmGrowBufPop(DMGrowBuf *buf) | |
128 { | |
129 if (buf != NULL && buf->adata != NULL && buf->nstack > 0) | |
130 { | |
131 DM_DBG("dmGrowBufPop(%p): size=%" DM_PRIu_SIZE_T "\n" | |
132 " nstack=%d [offs=%" DM_PRIu_SIZE_T ", len=%" DM_PRIu_SIZE_T "]\n", | |
133 buf, buf->size, buf->nstack, buf->offs, buf->len); | |
134 | |
135 buf->nstack--; | |
136 buf->offs = buf->stack[buf->nstack].offs; | |
137 buf->len += buf->stack[buf->nstack].len; | |
138 | |
139 buf->data = buf->adata + buf->offs; | |
140 | |
141 DM_DBG( | |
142 " nstack=%d [offs=%" DM_PRIu_SIZE_T ", len=%" DM_PRIu_SIZE_T "]\n", | |
143 buf->nstack, buf->offs, buf->len); | |
144 | |
145 } | |
146 else | |
147 DM_DBG("dmGrowBufPop(%p)\n", buf); | |
148 } | |
149 | |
150 | |
151 static BOOL dmGrowBufRealloc(DMGrowBuf *buf, const size_t nsize, const BOOL clear) | 100 static BOOL dmGrowBufRealloc(DMGrowBuf *buf, const size_t nsize, const BOOL clear) |
152 { | 101 { |
153 DM_DBG("dmGrowBufRealloc(%p): size=%" DM_PRIu_SIZE_T "\n" | 102 DM_DBG("dmGrowBufRealloc(%p):\n" |
154 " nstack=%d [offs=%" DM_PRIu_SIZE_T ", len=%" DM_PRIu_SIZE_T "]\n", | 103 " size=%" DM_PRIu_SIZE_T ", nsize=" DM_PRIu_SIZE_T |
155 buf, buf->size, buf->nstack, buf->offs, buf->len); | 104 ", nstack=%d, offs=%" DM_PRIu_SIZE_T "\n", |
156 | 105 buf, buf->size, nsize, buf->nstack, buf->offs); |
157 if ((buf->adata = dmRealloc(buf->adata, nsize)) == NULL) | 106 |
158 return FALSE; | 107 // Can't be smaller than current size! |
159 | 108 if (nsize < buf->size) |
109 return FALSE; | |
110 | |
111 if ((buf->data = dmRealloc(buf->data, nsize)) == NULL) | |
112 return FALSE; | |
113 | |
114 // For buffers growing backwards, we must move the | |
115 // current data to the end of the buffer .. | |
116 size_t clrsize = nsize - buf->size; | |
117 if (buf->backwards) | |
118 { | |
119 memmove(buf->data + clrsize, buf->data, clrsize); | |
120 buf->offs += clrsize; | |
121 } | |
122 | |
123 // Check if we need to clear the newly allocated area? | |
160 if (clear) | 124 if (clear) |
161 memset(buf->adata + buf->size, 0, nsize - buf->size); | 125 { |
162 | 126 if (buf->backwards) |
163 buf->data = buf->adata + buf->offs; | 127 memset(buf->data, 0, clrsize); |
128 else | |
129 memset(buf->data + buf->size, 0, clrsize); | |
130 } | |
131 | |
164 buf->size = nsize; | 132 buf->size = nsize; |
165 | 133 |
166 return TRUE; | 134 return TRUE; |
167 } | 135 } |
168 | 136 |
172 // if there is not enough space for at least that amount compared to | 140 // if there is not enough space for at least that amount compared to |
173 // current buffer "len". | 141 // current buffer "len". |
174 // | 142 // |
175 BOOL dmGrowBufGrow(DMGrowBuf *buf, const size_t amount) | 143 BOOL dmGrowBufGrow(DMGrowBuf *buf, const size_t amount) |
176 { | 144 { |
177 if (buf->adata == NULL || buf->offs + buf->len + amount >= buf->size) | 145 size_t grow = (amount > buf->mingrow) ? amount : buf->mingrow; |
178 { | 146 |
179 size_t grow = (amount > buf->mingrow) ? amount : buf->mingrow; | 147 if (buf->data == NULL || |
180 if (!dmGrowBufRealloc(buf, buf->offs + buf->len + grow, TRUE)) | 148 (buf->backwards && amount >= buf->offs) || |
149 (!buf->backwards && buf->offs + amount >= buf->size)) | |
150 { | |
151 if (!dmGrowBufRealloc(buf, buf->size + grow, TRUE)) | |
181 return FALSE; | 152 return FALSE; |
182 } | 153 } |
183 | 154 |
155 buf->len += amount; | |
184 return TRUE; | 156 return TRUE; |
185 } | 157 } |
186 | 158 |
187 | 159 |
188 // | 160 // |
189 // Grow the buffer if "nsize" is larger than the current buffer size. | 161 // Grow the buffer if "nsize" is larger than the current buffer size. |
190 // Buffer is enlarged to nsize + mingrow. | 162 // Buffer is enlarged to nsize + mingrow. |
191 // | 163 // |
192 BOOL dmGrowBufCheckGrow(DMGrowBuf *buf, const size_t nsize) | 164 BOOL dmGrowBufCheckGrow(DMGrowBuf *buf, const size_t nsize) |
193 { | 165 { |
194 if (buf->adata == NULL || buf->offs + nsize > buf->size) | 166 if (buf->data == NULL || nsize > buf->size) |
195 { | 167 { |
196 if (!dmGrowBufRealloc(buf, buf->offs + nsize + buf->mingrow, TRUE)) | 168 if (!dmGrowBufRealloc(buf, nsize + buf->mingrow, TRUE)) |
197 return FALSE; | 169 return FALSE; |
198 } | 170 } |
199 | 171 |
172 buf->len = nsize; | |
173 return TRUE; | |
174 } | |
175 | |
176 | |
177 static void dmGrowBufUpdate(DMGrowBuf *buf) | |
178 { | |
179 if (buf->offs < buf->min_offs) | |
180 buf->min_offs = buf->offs; | |
181 | |
182 if (buf->offs > buf->max_offs) | |
183 buf->max_offs = buf->offs; | |
184 } | |
185 | |
186 | |
187 BOOL dmGrowBufPut(DMGrowBuf *buf, const Uint8 *data, const size_t len) | |
188 { | |
189 if (data == NULL) | |
190 return FALSE; | |
191 | |
192 if (!dmGrowBufGrow(buf, len)) | |
193 return FALSE; | |
194 | |
195 if (buf->backwards) | |
196 { | |
197 if (buf->literal) | |
198 { | |
199 buf->offs -= len; | |
200 memcpy(buf->data + buf->offs, data, len); | |
201 } | |
202 else | |
203 { | |
204 for (size_t n = 0; n < len; n++) | |
205 buf->data[buf->offs--] = data[n]; | |
206 } | |
207 } | |
208 else | |
209 { | |
210 memcpy(buf->data + buf->offs, data, len); | |
211 buf->offs += len; | |
212 } | |
213 | |
214 dmGrowBufUpdate(buf); | |
215 | |
200 return TRUE; | 216 return TRUE; |
201 } | 217 } |
202 | 218 |
203 | 219 |
204 BOOL dmGrowBufPutU8(DMGrowBuf *buf, const Uint8 value) | 220 BOOL dmGrowBufPutU8(DMGrowBuf *buf, const Uint8 value) |
205 { | 221 { |
206 if (!dmGrowBufGrow(buf, sizeof(Uint8))) | 222 if (!dmGrowBufGrow(buf, sizeof(Uint8))) |
207 return FALSE; | 223 return FALSE; |
208 | 224 |
209 buf->data[buf->len++] = value; | 225 buf->data[buf->offs] = value; |
210 | 226 if (buf->backwards) |
211 return TRUE; | 227 buf->offs--; |
212 } | 228 else |
213 | 229 buf->offs++; |
214 | 230 |
215 BOOL dmGrowBufPut(DMGrowBuf *buf, const void *str, const size_t len) | 231 dmGrowBufUpdate(buf); |
216 { | |
217 if (str == NULL) | |
218 return FALSE; | |
219 | |
220 if (!dmGrowBufGrow(buf, len)) | |
221 return FALSE; | |
222 | |
223 memcpy(buf->data + buf->len, str, len); | |
224 buf->len += len; | |
225 | 232 |
226 return TRUE; | 233 return TRUE; |
227 } | 234 } |
228 | 235 |
229 | 236 |
230 BOOL dmGrowBufPutU16BE(DMGrowBuf *buf, const Uint16 val) | 237 BOOL dmGrowBufPutU16BE(DMGrowBuf *buf, const Uint16 val) |
231 { | 238 { |
232 if (!dmGrowBufGrow(buf, sizeof(Uint16))) | 239 if (buf->literal && buf->backwards) |
233 return FALSE; | 240 { |
234 | 241 return |
235 buf->data[buf->len++] = (val >> 8) & 0xff; | 242 !dmGrowBufPutU8(buf, val & 0xff) || |
236 buf->data[buf->len++] = val & 0xff; | 243 !dmGrowBufPutU8(buf, (val >> 8) & 0xff); |
237 | 244 } |
238 return TRUE; | 245 else |
246 { | |
247 return | |
248 !dmGrowBufPutU8(buf, (val >> 8) & 0xff) || | |
249 !dmGrowBufPutU8(buf, val & 0xff); | |
250 } | |
239 } | 251 } |
240 | 252 |
241 | 253 |
242 BOOL dmGrowBufPutU16LE(DMGrowBuf *buf, const Uint16 val) | 254 BOOL dmGrowBufPutU16LE(DMGrowBuf *buf, const Uint16 val) |
243 { | 255 { |
244 if (!dmGrowBufGrow(buf, sizeof(Uint16))) | 256 if (buf->literal && buf->backwards) |
245 return FALSE; | 257 { |
246 | 258 return |
247 buf->data[buf->len++] = val & 0xff; | 259 !dmGrowBufPutU8(buf, (val >> 8) & 0xff) || |
248 buf->data[buf->len++] = (val >> 8) & 0xff; | 260 !dmGrowBufPutU8(buf, val & 0xff); |
249 | 261 } |
250 return TRUE; | 262 else |
263 { | |
264 return | |
265 !dmGrowBufPutU8(buf, val & 0xff) || | |
266 !dmGrowBufPutU8(buf, (val >> 8) & 0xff); | |
267 } | |
251 } | 268 } |
252 | 269 |
253 | 270 |
254 BOOL dmGrowBufPutU32BE(DMGrowBuf *buf, const Uint32 val) | 271 BOOL dmGrowBufPutU32BE(DMGrowBuf *buf, const Uint32 val) |
255 { | 272 { |
256 if (!dmGrowBufGrow(buf, sizeof(Uint32))) | 273 if (buf->literal && buf->backwards) |
257 return FALSE; | 274 { |
258 | 275 return |
259 buf->data[buf->len++] = (val >> 24) & 0xff; | 276 !dmGrowBufPutU8(buf, (val >> 24) & 0xff) || |
260 buf->data[buf->len++] = (val >> 16) & 0xff; | 277 !dmGrowBufPutU8(buf, (val >> 16) & 0xff) || |
261 buf->data[buf->len++] = (val >> 8) & 0xff; | 278 !dmGrowBufPutU8(buf, (val >> 8) & 0xff) || |
262 buf->data[buf->len++] = val & 0xff; | 279 !dmGrowBufPutU8(buf, val & 0xff); |
263 | 280 } |
264 return TRUE; | 281 else |
282 { | |
283 return | |
284 !dmGrowBufPutU8(buf, val & 0xff) || | |
285 !dmGrowBufPutU8(buf, (val >> 8) & 0xff) || | |
286 !dmGrowBufPutU8(buf, (val >> 16) & 0xff) || | |
287 !dmGrowBufPutU8(buf, (val >> 24) & 0xff); | |
288 } | |
265 } | 289 } |
266 | 290 |
267 | 291 |
268 BOOL dmGrowBufPutU32LE(DMGrowBuf *buf, const Uint32 val) | 292 BOOL dmGrowBufPutU32LE(DMGrowBuf *buf, const Uint32 val) |
269 { | 293 { |
270 if (!dmGrowBufGrow(buf, sizeof(Uint32))) | 294 if (buf->literal && buf->backwards) |
271 return FALSE; | 295 { |
272 | 296 return |
273 buf->data[buf->len++] = val & 0xff; | 297 !dmGrowBufPutU8(buf, val & 0xff) || |
274 buf->data[buf->len++] = (val >> 8) & 0xff; | 298 !dmGrowBufPutU8(buf, (val >> 8) & 0xff) || |
275 buf->data[buf->len++] = (val >> 16) & 0xff; | 299 !dmGrowBufPutU8(buf, (val >> 16) & 0xff) || |
276 buf->data[buf->len++] = (val >> 24) & 0xff; | 300 !dmGrowBufPutU8(buf, (val >> 24) & 0xff); |
277 | 301 } |
278 return TRUE; | 302 else |
279 } | 303 { |
304 return | |
305 !dmGrowBufPutU8(buf, (val >> 24) & 0xff) || | |
306 !dmGrowBufPutU8(buf, (val >> 16) & 0xff) || | |
307 !dmGrowBufPutU8(buf, (val >> 8) & 0xff) || | |
308 !dmGrowBufPutU8(buf, val & 0xff); | |
309 } | |
310 } |