/** * \brief Get a block of data if possible, and see if it matches. * * On each call, we try to process all of the input data available on the * scoop and input buffer. */ static rs_result rs_delta_s_scan(rs_job_t *job) { rs_long_t match_pos; size_t match_len; rs_result result; Rollsum test; rs_job_check(job); /* read the input into the scoop */ rs_getinput(job); /* output any pending output from the tube */ result=rs_tube_catchup(job); /* while output is not blocked and there is a block of data */ while ((result==RS_DONE) && ((job->scoop_pos + job->block_len) < job->scoop_avail)) { /* check if this block matches */ if (rs_findmatch(job,&match_pos,&match_len)) { /* append the match and reset the weak_sum */ result=rs_appendmatch(job,match_pos,match_len); RollsumInit(&job->weak_sum); } else { /* rotate the weak_sum and append the miss byte */ RollsumRotate(&job->weak_sum,job->scoop_next[job->scoop_pos], job->scoop_next[job->scoop_pos+job->block_len]); result=rs_appendmiss(job,1); if (rs_roll_paranoia) { RollsumInit(&test); RollsumUpdate(&test,job->scoop_next+job->scoop_pos, job->block_len); if (RollsumDigest(&test) != RollsumDigest(&job->weak_sum)) { rs_fatal("mismatch between rolled sum %#x and check %#x", (int)RollsumDigest(&job->weak_sum), (int)RollsumDigest(&test)); } } } } /* if we completed OK */ if (result==RS_DONE) { /* if we reached eof, we can flush the last fragment */ if (job->stream->eof_in) { job->statefn=rs_delta_s_flush; return RS_RUNNING; } else { /* we are blocked waiting for more data */ return RS_BLOCKED; } } return result; }
/** * find a match at scoop_pos, returning the match_pos and match_len. * Note that this will calculate weak_sum if required. It will also * determine the match_len. * * Note that this routine could be modified to do xdelta style matches that * would extend matches past block boundaries by matching backwards and * forwards beyond the block boundaries. Extending backwards would require * decrementing scoop_pos as appropriate. */ INLINE int rs_findmatch(rs_job_t *job, rs_long_t *match_pos, size_t *match_len) { /* calculate the weak_sum if we don't have one */ if (job->weak_sum.count == 0) { /* set match_len to min(block_len, scan_avail) */ *match_len=job->scoop_avail - job->scoop_pos; if (*match_len > job->block_len) { *match_len = job->block_len; } /* Update the weak_sum */ RollsumUpdate(&job->weak_sum,job->scoop_next+job->scoop_pos,*match_len); rs_trace("calculate weak sum from scratch length %d",(int)job->weak_sum.count); } else { /* set the match_len to the weak_sum count */ *match_len=job->weak_sum.count; } return rs_search_for_block(RollsumDigest(&job->weak_sum), job->scoop_next+job->scoop_pos, *match_len, job->signature, &job->stats, match_pos); }
int main(int argc, char *argv[]) { int i; Rollsum sum; char c,data[BLOCKSIZE]; unsigned long digest; if (argc != 1) { usage(); } for (i=0;i<BLOCKSIZE;i++) { data[i]=(char)(i & 0xff); } RollsumInit(&sum); RollsumUpdate(&sum,data,BLOCKSIZE); for (i=0;i<(COUNT*BLOCKSIZE);i++) { c=data[i % BLOCKSIZE]; RollsumRotate(&sum,c,c); digest=RollsumDigest(&sum); } printf("rollsum: %i x %i rotate gives %X\n",COUNT,BLOCKSIZE,digest); }