| 203 } |
203 } |
| 204 } |
204 } |
| 205 |
205 |
| 206 static size_t cx_buffer_flush_helper( |
206 static size_t cx_buffer_flush_helper( |
| 207 const CxBuffer *buffer, |
207 const CxBuffer *buffer, |
| |
208 const unsigned char *src, |
| 208 size_t size, |
209 size_t size, |
| 209 const unsigned char *src, |
|
| 210 size_t nitems |
210 size_t nitems |
| 211 ) { |
211 ) { |
| 212 // flush data from an arbitrary source |
212 // flush data from an arbitrary source |
| 213 // does not need to be the buffer's contents |
213 // does not need to be the buffer's contents |
| 214 size_t max_items = buffer->flush->blksize / size; |
214 size_t max_items = buffer->flush->blksize / size; |
| 234 static size_t cx_buffer_flush_impl(CxBuffer *buffer, size_t size) { |
234 static size_t cx_buffer_flush_impl(CxBuffer *buffer, size_t size) { |
| 235 // flush the current contents of the buffer |
235 // flush the current contents of the buffer |
| 236 unsigned char *space = buffer->bytes; |
236 unsigned char *space = buffer->bytes; |
| 237 size_t remaining = buffer->pos / size; |
237 size_t remaining = buffer->pos / size; |
| 238 size_t flushed_total = cx_buffer_flush_helper( |
238 size_t flushed_total = cx_buffer_flush_helper( |
| 239 buffer, size, space, remaining); |
239 buffer, space, size, remaining); |
| 240 |
240 |
| 241 // shift the buffer left after flushing |
241 // shift the buffer left after flushing |
| 242 // IMPORTANT: up to this point, copy on write must have been |
242 // IMPORTANT: up to this point, copy on write must have been |
| 243 // performed already, because we can't do error handling here |
243 // performed already, because we can't do error handling here |
| 244 cxBufferShiftLeft(buffer, flushed_total*size); |
244 cxBufferShiftLeft(buffer, flushed_total*size); |
| 315 if (perform_flush) { |
315 if (perform_flush) { |
| 316 size_t items_flush; |
316 size_t items_flush; |
| 317 if (buffer->pos == 0) { |
317 if (buffer->pos == 0) { |
| 318 // if we don't have data in the buffer, but are instructed |
318 // if we don't have data in the buffer, but are instructed |
| 319 // to flush, it means that we are supposed to relay the data |
319 // to flush, it means that we are supposed to relay the data |
| 320 items_flush = cx_buffer_flush_helper(buffer, size, ptr, nitems); |
320 items_flush = cx_buffer_flush_helper(buffer, ptr, size, nitems); |
| 321 if (items_flush == 0) { |
321 if (items_flush == 0) { |
| 322 // we needed to flush, but could not flush anything |
322 // we needed to flush, but could not flush anything |
| 323 // give up and avoid endless trying |
323 // give up and avoid endless trying |
| 324 return 0; |
324 return 0; |
| 325 } |
325 } |
| 326 size_t ritems = nitems - items_flush; |
326 size_t ritems = nitems - items_flush; |
| 327 const unsigned char *rest = ptr; |
327 if (ritems > 0) { |
| 328 rest += items_flush * size; |
328 const unsigned char *rest = ptr; |
| 329 return items_flush + cxBufferWrite(rest, size, ritems, buffer); |
329 rest += items_flush * size; |
| |
330 return items_flush + cxBufferWrite(rest, size, ritems, buffer); |
| |
331 } else { |
| |
332 return items_flush; |
| |
333 } |
| 330 } else { |
334 } else { |
| 331 items_flush = cx_buffer_flush_impl(buffer, size); |
335 items_flush = cx_buffer_flush_impl(buffer, size); |
| 332 if (items_flush == 0) { |
336 if (items_flush == 0) { |
| 333 return 0; |
337 return 0; |
| 334 } |
338 } |