static void iostream_pump_copy(struct iostream_pump *pump) { enum ostream_send_istream_result res; size_t old_size; o_stream_cork(pump->output); old_size = o_stream_get_max_buffer_size(pump->output); o_stream_set_max_buffer_size(pump->output, I_MIN(IO_BLOCK_SIZE, o_stream_get_max_buffer_size(pump->output))); res = o_stream_send_istream(pump->output, pump->input); o_stream_set_max_buffer_size(pump->output, old_size); o_stream_uncork(pump->output); switch(res) { case OSTREAM_SEND_ISTREAM_RESULT_ERROR_INPUT: io_remove(&pump->io); pump->callback(IOSTREAM_PUMP_STATUS_INPUT_ERROR, pump->context); return; case OSTREAM_SEND_ISTREAM_RESULT_ERROR_OUTPUT: io_remove(&pump->io); pump->callback(IOSTREAM_PUMP_STATUS_OUTPUT_ERROR, pump->context); return; case OSTREAM_SEND_ISTREAM_RESULT_WAIT_OUTPUT: i_assert(!pump->output->blocking); pump->waiting_output = TRUE; io_remove(&pump->io); return; case OSTREAM_SEND_ISTREAM_RESULT_FINISHED: pump->waiting_output = FALSE; io_remove(&pump->io); /* flush it */ switch (o_stream_flush(pump->output)) { case -1: pump->callback(IOSTREAM_PUMP_STATUS_OUTPUT_ERROR, pump->context); break; case 0: pump->waiting_output = TRUE; pump->completed = TRUE; break; default: pump->callback(IOSTREAM_PUMP_STATUS_INPUT_EOF, pump->context); break; } return; case OSTREAM_SEND_ISTREAM_RESULT_WAIT_INPUT: i_assert(!pump->input->blocking); pump->waiting_output = FALSE; return; } i_unreached(); }
static ssize_t o_stream_escaped_send_chunk(struct escaped_ostream *estream, const unsigned char *data, size_t len) { size_t i, max_buffer_size; ssize_t ret; max_buffer_size = I_MIN(o_stream_get_max_buffer_size(estream->ostream.parent), estream->ostream.max_buffer_size); if (max_buffer_size > IO_BLOCK_SIZE) { /* avoid using up too much memory in case of large buffers */ max_buffer_size = IO_BLOCK_SIZE; } for (i = 0; i < len; i++) { if (str_len(estream->buf) + 2 > max_buffer_size) { /* escaping takes at least two bytes */ ret = o_stream_escaped_send_outbuf(estream); if (ret < 0) { estream->ostream.ostream.offset += i; return ret; } if (ret == 0) break; } estream->format(estream->buf, data[i]); estream->flushed = FALSE; } estream->ostream.ostream.offset += i; return i; }
struct ostream * o_stream_create_escaped(struct ostream *output, ostream_escaped_escape_formatter_t format) { struct escaped_ostream *estream; estream = i_new(struct escaped_ostream, 1); estream->ostream.sendv = o_stream_escaped_sendv; estream->ostream.flush = o_stream_escaped_flush; estream->ostream.max_buffer_size = o_stream_get_max_buffer_size(output); estream->ostream.iostream.destroy = o_stream_escaped_destroy; estream->buf = str_new(default_pool, 512); estream->format = format; estream->flushed = FALSE; return o_stream_create(&estream->ostream, output, o_stream_get_fd(output)); }