#include "config.h"
#include <assert.h>
#include <stdlib.h>
#include <string.h>
#include "librsync.h"
#include "job.h"
#include "stream.h"
#include "trace.h"
static void rs_tube_catchup_write(rs_job_t *job)
{
rs_buffers_t *stream = job->stream;
int len = job->write_len;
assert(len > 0);
if ((size_t)len > stream->avail_out)
len = stream->avail_out;
if (!stream->avail_out) {
rs_trace("no output space available");
return;
}
memcpy(stream->next_out, job->write_buf, len);
stream->next_out += len;
stream->avail_out -= len;
job->write_len -= len;
if (job->write_len > 0) {
memmove(job->write_buf, job->write_buf + len, job->write_len);
}
rs_trace("wrote %d bytes from tube, %d remaining", len, job->write_len);
}
static void rs_tube_copy_from_scoop(rs_job_t *job)
{
rs_buffers_t *stream = job->stream;
size_t len = job->copy_len;
assert(len > 0);
if (len > job->scoop_avail)
len = job->scoop_avail;
if (len > stream->avail_out)
len = stream->avail_out;
memcpy(stream->next_out, job->scoop_next, len);
stream->next_out += len;
stream->avail_out -= len;
job->scoop_avail -= len;
job->scoop_next += len;
job->copy_len -= len;
rs_trace("caught up on " FMT_SIZE " copied bytes from scoop, " FMT_SIZE
" remain there, " FMT_LONG " remain to be copied", len,
job->scoop_avail, job->copy_len);
}
static void rs_tube_catchup_copy(rs_job_t *job)
{
assert(job->write_len == 0);
assert(job->copy_len > 0);
if (job->scoop_avail && job->copy_len) {
rs_tube_copy_from_scoop(job);
}
if (job->copy_len && !job->scoop_avail) {
size_t this_copy = rs_buffers_copy(job->stream, job->copy_len);
job->copy_len -= this_copy;
rs_trace("copied " FMT_SIZE " bytes from input buffer, " FMT_LONG
" remain to be copied", this_copy, job->copy_len);
}
}
int rs_tube_catchup(rs_job_t *job)
{
if (job->write_len) {
rs_tube_catchup_write(job);
if (job->write_len)
return RS_BLOCKED;
}
if (job->copy_len) {
rs_tube_catchup_copy(job);
if (job->copy_len) {
if (job->stream->eof_in && !job->stream->avail_in
&& !job->scoop_avail) {
rs_error
("reached end of file while copying literal data through buffers");
return RS_INPUT_ENDED;
}
return RS_BLOCKED;
}
}
return RS_DONE;
}
int rs_tube_is_idle(rs_job_t const *job)
{
return job->write_len == 0 && job->copy_len == 0;
}
void rs_tube_copy(rs_job_t *job, int len)
{
assert(job->copy_len == 0);
job->copy_len = len;
}
void rs_tube_write(rs_job_t *job, const void *buf, size_t len)
{
assert(job->copy_len == 0);
assert(len <= sizeof(job->write_buf) - job->write_len);
memcpy(job->write_buf + job->write_len, buf, len);
job->write_len += len;
}