svn_error_t *svn_txdelta_send_stream(svn_stream_t *stream, svn_txdelta_window_handler_t handler, void *handler_baton, unsigned char *digest, apr_pool_t *pool) { svn_txdelta_window_t delta_window = { 0 }; svn_txdelta_op_t delta_op; svn_string_t window_data; char read_buf[SVN__STREAM_CHUNK_SIZE + 1]; svn_checksum_ctx_t *md5_checksum_ctx; if (digest) md5_checksum_ctx = svn_checksum_ctx_create(svn_checksum_md5, pool); while (1) { apr_size_t read_len = SVN__STREAM_CHUNK_SIZE; SVN_ERR(svn_stream_read_full(stream, read_buf, &read_len)); if (read_len == 0) break; window_data.data = read_buf; window_data.len = read_len; delta_op.action_code = svn_txdelta_new; delta_op.offset = 0; delta_op.length = read_len; delta_window.tview_len = read_len; delta_window.num_ops = 1; delta_window.ops = &delta_op; delta_window.new_data = &window_data; SVN_ERR(handler(&delta_window, handler_baton)); if (digest) SVN_ERR(svn_checksum_update(md5_checksum_ctx, read_buf, read_len)); if (read_len < SVN__STREAM_CHUNK_SIZE) break; } SVN_ERR(handler(NULL, handler_baton)); if (digest) { svn_checksum_t *md5_checksum; SVN_ERR(svn_checksum_final(&md5_checksum, md5_checksum_ctx, pool)); memcpy(digest, md5_checksum->digest, APR_MD5_DIGESTSIZE); } return SVN_NO_ERROR; }
svn_error_t * svn_txdelta_run(svn_stream_t *source, svn_stream_t *target, svn_txdelta_window_handler_t handler, void *handler_baton, svn_checksum_kind_t checksum_kind, svn_checksum_t **checksum, svn_cancel_func_t cancel_func, void *cancel_baton, apr_pool_t *result_pool, apr_pool_t *scratch_pool) { apr_pool_t *iterpool = svn_pool_create(scratch_pool); struct txdelta_baton tb = { 0 }; svn_txdelta_window_t *window; tb.source = source; tb.target = target; tb.more_source = TRUE; tb.more = TRUE; tb.pos = 0; tb.buf = apr_palloc(scratch_pool, 2 * SVN_DELTA_WINDOW_SIZE); tb.result_pool = result_pool; if (checksum != NULL) tb.context = svn_checksum_ctx_create(checksum_kind, scratch_pool); do { /* free the window (if any) */ svn_pool_clear(iterpool); /* read in a single delta window */ SVN_ERR(txdelta_next_window(&window, &tb, iterpool)); /* shove it at the handler */ SVN_ERR((*handler)(window, handler_baton)); if (cancel_func) SVN_ERR(cancel_func(cancel_baton)); } while (window != NULL); svn_pool_destroy(iterpool); if (checksum != NULL) *checksum = tb.checksum; /* should be there! */ return SVN_NO_ERROR; }
svn_stream_t * svn_stream_checksummed2(svn_stream_t *stream, svn_checksum_t **read_checksum, svn_checksum_t **write_checksum, svn_checksum_kind_t checksum_kind, svn_boolean_t read_all, apr_pool_t *pool) { svn_stream_t *s; struct checksum_stream_baton *baton; if (read_checksum == NULL && write_checksum == NULL) return stream; baton = apr_palloc(pool, sizeof(*baton)); if (read_checksum) baton->read_ctx = svn_checksum_ctx_create(checksum_kind, pool); else baton->read_ctx = NULL; if (write_checksum) baton->write_ctx = svn_checksum_ctx_create(checksum_kind, pool); else baton->write_ctx = NULL; baton->read_checksum = read_checksum; baton->write_checksum = write_checksum; baton->proxy = stream; baton->read_more = read_all; baton->pool = pool; s = svn_stream_create(baton, pool); svn_stream_set_read(s, read_handler_checksum); svn_stream_set_write(s, write_handler_checksum); svn_stream_set_close(s, close_handler_checksum); return s; }
void svn_txdelta(svn_txdelta_stream_t **stream, svn_stream_t *source, svn_stream_t *target, apr_pool_t *pool) { struct txdelta_baton *b = apr_pcalloc(pool, sizeof(*b)); b->source = source; b->target = target; b->more_source = TRUE; b->more = TRUE; b->buf = apr_palloc(pool, 2 * SVN_DELTA_WINDOW_SIZE); b->context = svn_checksum_ctx_create(svn_checksum_md5, pool); b->result_pool = pool; *stream = svn_txdelta_stream_create(b, txdelta_next_window, txdelta_md5_digest, pool); }