| 259 } else { |
259 } else { |
| 260 return -1; // LCOV_EXCL_LINE |
260 return -1; // LCOV_EXCL_LINE |
| 261 } |
261 } |
| 262 } |
262 } |
| 263 |
263 |
| 264 int cxBufferMinimumCapacity(CxBuffer *buffer, size_t newcap) { |
264 static size_t cx_buffer_calculate_minimum_capacity(size_t mincap) { |
| 265 if (newcap <= buffer->capacity) { |
|
| 266 return 0; |
|
| 267 } |
|
| 268 |
|
| 269 unsigned long pagesize = system_page_size(); |
265 unsigned long pagesize = system_page_size(); |
| 270 // if page size is larger than 64 KB - for some reason - truncate to 64 KB |
266 // if page size is larger than 64 KB - for some reason - truncate to 64 KB |
| 271 if (pagesize > 65536) pagesize = 65536; |
267 if (pagesize > 65536) pagesize = 65536; |
| 272 if (newcap < pagesize) { |
268 if (mincap < pagesize) { |
| 273 // when smaller as one page, map to the next power of two |
269 // when smaller as one page, map to the next power of two |
| 274 newcap--; |
270 mincap--; |
| 275 newcap |= newcap >> 1; |
271 mincap |= mincap >> 1; |
| 276 newcap |= newcap >> 2; |
272 mincap |= mincap >> 2; |
| 277 newcap |= newcap >> 4; |
273 mincap |= mincap >> 4; |
| 278 // last operation only needed for pages larger 4096 bytes |
274 // last operation only needed for pages larger 4096 bytes |
| 279 // but if/else would be more expensive than just doing this |
275 // but if/else would be more expensive than just doing this |
| 280 newcap |= newcap >> 8; |
276 mincap |= mincap >> 8; |
| 281 newcap++; |
277 mincap++; |
| 282 } else { |
278 } else { |
| 283 // otherwise, map to a multiple of the page size |
279 // otherwise, map to a multiple of the page size |
| 284 newcap -= newcap % pagesize; |
280 mincap -= mincap % pagesize; |
| 285 newcap += pagesize; |
281 mincap += pagesize; |
| 286 // note: if newcap is already page aligned, |
282 // note: if newcap is already page aligned, |
| 287 // this gives a full additional page (which is good) |
283 // this gives a full additional page (which is good) |
| 288 } |
284 } |
| 289 |
285 return mincap; |
| |
286 } |
| |
287 |
| |
288 int cxBufferMinimumCapacity(CxBuffer *buffer, size_t newcap) { |
| |
289 if (newcap <= buffer->capacity) { |
| |
290 return 0; |
| |
291 } |
| |
292 newcap = cx_buffer_calculate_minimum_capacity(newcap); |
| 290 return cxBufferReserve(buffer, newcap); |
293 return cxBufferReserve(buffer, newcap); |
| 291 } |
294 } |
| 292 |
295 |
| 293 void cxBufferShrink( |
296 void cxBufferShrink( |
| 294 CxBuffer *buffer, |
297 CxBuffer *buffer, |
| 390 |
393 |
| 391 size_t required = buffer->pos + len; |
394 size_t required = buffer->pos + len; |
| 392 bool perform_flush = false; |
395 bool perform_flush = false; |
| 393 if (required > buffer->capacity) { |
396 if (required > buffer->capacity) { |
| 394 if (buffer->flags & CX_BUFFER_AUTO_EXTEND) { |
397 if (buffer->flags & CX_BUFFER_AUTO_EXTEND) { |
| 395 if (buffer->flush != NULL && required > buffer->flush->threshold) { |
398 if (buffer->flush != NULL) { |
| 396 perform_flush = true; |
399 size_t newcap = cx_buffer_calculate_minimum_capacity(required); |
| |
400 if (newcap > buffer->flush->threshold) { |
| |
401 newcap = buffer->flush->threshold; |
| |
402 } |
| |
403 if (cxBufferReserve(buffer, newcap)) { |
| |
404 return total_flushed; // LCOV_EXCL_LINE |
| |
405 } |
| |
406 if (required > newcap) { |
| |
407 perform_flush = true; |
| |
408 } |
| 397 } else { |
409 } else { |
| 398 if (cxBufferMinimumCapacity(buffer, required)) { |
410 if (cxBufferMinimumCapacity(buffer, required)) { |
| 399 return total_flushed; // LCOV_EXCL_LINE |
411 return total_flushed; // LCOV_EXCL_LINE |
| 400 } |
412 } |
| 401 } |
413 } |