File Annotation
Not logged in
dbda8d6ce9 2007-07-21       drh: /*
dbda8d6ce9 2007-07-21       drh: ** Copyright (c) 2006 D. Richard Hipp
dbda8d6ce9 2007-07-21       drh: **
dbda8d6ce9 2007-07-21       drh: ** This program is free software; you can redistribute it and/or
dbda8d6ce9 2007-07-21       drh: ** modify it under the terms of the GNU General Public
dbda8d6ce9 2007-07-21       drh: ** License version 2 as published by the Free Software Foundation.
dbda8d6ce9 2007-07-21       drh: **
dbda8d6ce9 2007-07-21       drh: ** This program is distributed in the hope that it will be useful,
dbda8d6ce9 2007-07-21       drh: ** but WITHOUT ANY WARRANTY; without even the implied warranty of
dbda8d6ce9 2007-07-21       drh: ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
dbda8d6ce9 2007-07-21       drh: ** General Public License for more details.
dbda8d6ce9 2007-07-21       drh: **
dbda8d6ce9 2007-07-21       drh: ** You should have received a copy of the GNU General Public
dbda8d6ce9 2007-07-21       drh: ** License along with this library; if not, write to the
dbda8d6ce9 2007-07-21       drh: ** Free Software Foundation, Inc., 59 Temple Place - Suite 330,
dbda8d6ce9 2007-07-21       drh: ** Boston, MA  02111-1307, USA.
dbda8d6ce9 2007-07-21       drh: **
dbda8d6ce9 2007-07-21       drh: ** Author contact information:
dbda8d6ce9 2007-07-21       drh: **   drh@hwaci.com
dbda8d6ce9 2007-07-21       drh: **   http://www.hwaci.com/drh/
dbda8d6ce9 2007-07-21       drh: **
dbda8d6ce9 2007-07-21       drh: *******************************************************************************
dbda8d6ce9 2007-07-21       drh: **
dbda8d6ce9 2007-07-21       drh: ** This module implements the interface to the delta generator.
dbda8d6ce9 2007-07-21       drh: */
dbda8d6ce9 2007-07-21       drh: #include "config.h"
dbda8d6ce9 2007-07-21       drh: #include "deltacmd.h"
dbda8d6ce9 2007-07-21       drh: 
dbda8d6ce9 2007-07-21       drh: /*
dbda8d6ce9 2007-07-21       drh: ** Create a delta that describes the change from pOriginal to pTarget
dbda8d6ce9 2007-07-21       drh: ** and put that delta in pDelta.  The pDelta blob is assumed to be
dbda8d6ce9 2007-07-21       drh: ** uninitialized.
dbda8d6ce9 2007-07-21       drh: */
dbda8d6ce9 2007-07-21       drh: int blob_delta_create(Blob *pOriginal, Blob *pTarget, Blob *pDelta){
dbda8d6ce9 2007-07-21       drh:   blob_zero(pDelta);
dbda8d6ce9 2007-07-21       drh:   const char *zOrig, *zTarg;
dbda8d6ce9 2007-07-21       drh:   int lenOrig, lenTarg;
dbda8d6ce9 2007-07-21       drh:   int len;
dbda8d6ce9 2007-07-21       drh:   char *zRes;
dbda8d6ce9 2007-07-21       drh:   zOrig = blob_buffer(pOriginal);
dbda8d6ce9 2007-07-21       drh:   lenOrig = blob_size(pOriginal);
dbda8d6ce9 2007-07-21       drh:   zTarg = blob_buffer(pTarget);
dbda8d6ce9 2007-07-21       drh:   lenTarg = blob_size(pTarget);
dbda8d6ce9 2007-07-21       drh:   blob_resize(pDelta, lenTarg+16);
dbda8d6ce9 2007-07-21       drh:   zRes = blob_buffer(pDelta);
dbda8d6ce9 2007-07-21       drh:   len = delta_create(zOrig, lenOrig, zTarg, lenTarg, zRes);
dbda8d6ce9 2007-07-21       drh:   blob_resize(pDelta, len);
dbda8d6ce9 2007-07-21       drh:   return 0;
dbda8d6ce9 2007-07-21       drh: }
dbda8d6ce9 2007-07-21       drh: 
dbda8d6ce9 2007-07-21       drh: /*
dbda8d6ce9 2007-07-21       drh: ** COMMAND:  test-delta-create
dbda8d6ce9 2007-07-21       drh: **
dbda8d6ce9 2007-07-21       drh: ** Given two input files, create and output a delta that carries
dbda8d6ce9 2007-07-21       drh: ** the first file into the second.
dbda8d6ce9 2007-07-21       drh: */
dbda8d6ce9 2007-07-21       drh: void delta_create_cmd(void){
dbda8d6ce9 2007-07-21       drh:   Blob orig, target, delta;
dbda8d6ce9 2007-07-21       drh:   if( g.argc!=5 ){
dbda8d6ce9 2007-07-21       drh:     fprintf(stderr,"Usage: %s %s ORIGIN TARGET DELTA\n", g.argv[0], g.argv[1]);
dbda8d6ce9 2007-07-21       drh:     exit(1);
dbda8d6ce9 2007-07-21       drh:   }
dbda8d6ce9 2007-07-21       drh:   if( blob_read_from_file(&orig, g.argv[2])<0 ){
dbda8d6ce9 2007-07-21       drh:     fprintf(stderr,"cannot read %s\n", g.argv[2]);
dbda8d6ce9 2007-07-21       drh:     exit(1);
dbda8d6ce9 2007-07-21       drh:   }
dbda8d6ce9 2007-07-21       drh:   if( blob_read_from_file(&target, g.argv[3])<0 ){
dbda8d6ce9 2007-07-21       drh:     fprintf(stderr,"cannot read %s\n", g.argv[3]);
dbda8d6ce9 2007-07-21       drh:     exit(1);
dbda8d6ce9 2007-07-21       drh:   }
dbda8d6ce9 2007-07-21       drh:   blob_delta_create(&orig, &target, &delta);
dbda8d6ce9 2007-07-21       drh:   if( blob_write_to_file(&delta, g.argv[4])<blob_size(&delta) ){
dbda8d6ce9 2007-07-21       drh:     fprintf(stderr,"cannot write %s\n", g.argv[4]);
dbda8d6ce9 2007-07-21       drh:     exit(1);
dbda8d6ce9 2007-07-21       drh:   }
dbda8d6ce9 2007-07-21       drh:   blob_reset(&orig);
dbda8d6ce9 2007-07-21       drh:   blob_reset(&target);
dbda8d6ce9 2007-07-21       drh:   blob_reset(&delta);
dbda8d6ce9 2007-07-21       drh: }
dbda8d6ce9 2007-07-21       drh: 
dbda8d6ce9 2007-07-21       drh: /*
dbda8d6ce9 2007-07-21       drh: ** Apply the delta in pDelta to the original file pOriginal to generate
dbda8d6ce9 2007-07-21       drh: ** the target file pTarget.  The pTarget blob is initialized by this
dbda8d6ce9 2007-07-21       drh: ** routine.
dbda8d6ce9 2007-07-21       drh: **
dbda8d6ce9 2007-07-21       drh: ** It works ok for pTarget and pOriginal to be the same blob.
dbda8d6ce9 2007-07-21       drh: **
dbda8d6ce9 2007-07-21       drh: ** Return the length of the target.  Return -1 if there is an error.
dbda8d6ce9 2007-07-21       drh: */
dbda8d6ce9 2007-07-21       drh: int blob_delta_apply(Blob *pOriginal, Blob *pDelta, Blob *pTarget){
dbda8d6ce9 2007-07-21       drh:   int len, n;
dbda8d6ce9 2007-07-21       drh:   Blob out;
dbda8d6ce9 2007-07-21       drh: 
dbda8d6ce9 2007-07-21       drh:   n = delta_output_size(blob_buffer(pDelta), blob_size(pDelta));
dbda8d6ce9 2007-07-21       drh:   blob_zero(&out);
dbda8d6ce9 2007-07-21       drh:   blob_resize(&out, n);
dbda8d6ce9 2007-07-21       drh:   len = delta_apply(
dbda8d6ce9 2007-07-21       drh:      blob_buffer(pOriginal), blob_size(pOriginal),
dbda8d6ce9 2007-07-21       drh:      blob_buffer(pDelta), blob_size(pDelta),
dbda8d6ce9 2007-07-21       drh:      blob_buffer(&out));
dbda8d6ce9 2007-07-21       drh:   if( len<0 ){
dbda8d6ce9 2007-07-21       drh:     blob_reset(&out);
dbda8d6ce9 2007-07-21       drh:   }else if( len!=n ){
dbda8d6ce9 2007-07-21       drh:     blob_resize(&out, len);
dbda8d6ce9 2007-07-21       drh:   }
dbda8d6ce9 2007-07-21       drh:   if( pTarget==pOriginal ){
dbda8d6ce9 2007-07-21       drh:     blob_reset(pOriginal);
dbda8d6ce9 2007-07-21       drh:   }
dbda8d6ce9 2007-07-21       drh:   *pTarget = out;
dbda8d6ce9 2007-07-21       drh:   return len;
dbda8d6ce9 2007-07-21       drh: }
dbda8d6ce9 2007-07-21       drh: 
dbda8d6ce9 2007-07-21       drh: /*
dbda8d6ce9 2007-07-21       drh: ** COMMAND:  test-delta-apply
dbda8d6ce9 2007-07-21       drh: **
dbda8d6ce9 2007-07-21       drh: ** Given an input files and a delta, apply the delta to the input file
dbda8d6ce9 2007-07-21       drh: ** and write the result.
dbda8d6ce9 2007-07-21       drh: */
dbda8d6ce9 2007-07-21       drh: void delta_apply_cmd(void){
dbda8d6ce9 2007-07-21       drh:   Blob orig, target, delta;
dbda8d6ce9 2007-07-21       drh:   if( g.argc!=5 ){
dbda8d6ce9 2007-07-21       drh:     fprintf(stderr,"Usage: %s %s ORIGIN DELTA TARGET\n", g.argv[0], g.argv[1]);
dbda8d6ce9 2007-07-21       drh:     exit(1);
dbda8d6ce9 2007-07-21       drh:   }
dbda8d6ce9 2007-07-21       drh:   if( blob_read_from_file(&orig, g.argv[2])<0 ){
dbda8d6ce9 2007-07-21       drh:     fprintf(stderr,"cannot read %s\n", g.argv[2]);
dbda8d6ce9 2007-07-21       drh:     exit(1);
dbda8d6ce9 2007-07-21       drh:   }
dbda8d6ce9 2007-07-21       drh:   if( blob_read_from_file(&delta, g.argv[3])<0 ){
dbda8d6ce9 2007-07-21       drh:     fprintf(stderr,"cannot read %s\n", g.argv[3]);
dbda8d6ce9 2007-07-21       drh:     exit(1);
dbda8d6ce9 2007-07-21       drh:   }
dbda8d6ce9 2007-07-21       drh:   blob_delta_apply(&orig, &delta, &target);
dbda8d6ce9 2007-07-21       drh:   if( blob_write_to_file(&target, g.argv[4])<blob_size(&target) ){
dbda8d6ce9 2007-07-21       drh:     fprintf(stderr,"cannot write %s\n", g.argv[4]);
dbda8d6ce9 2007-07-21       drh:     exit(1);
dbda8d6ce9 2007-07-21       drh:   }
dbda8d6ce9 2007-07-21       drh:   blob_reset(&orig);
dbda8d6ce9 2007-07-21       drh:   blob_reset(&target);
dbda8d6ce9 2007-07-21       drh:   blob_reset(&delta);
dbda8d6ce9 2007-07-21       drh: }
dbda8d6ce9 2007-07-21       drh: 
dbda8d6ce9 2007-07-21       drh: /*
dbda8d6ce9 2007-07-21       drh: ** COMMAND:  test-delta
dbda8d6ce9 2007-07-21       drh: **
dbda8d6ce9 2007-07-21       drh: ** Read two files named on the command-line.  Create and apply deltas
dbda8d6ce9 2007-07-21       drh: ** going in both directions.  Verify that the original files are
dbda8d6ce9 2007-07-21       drh: ** correctly recovered.
dbda8d6ce9 2007-07-21       drh: */
dbda8d6ce9 2007-07-21       drh: void cmd_test_delta(void){
dbda8d6ce9 2007-07-21       drh:   Blob f1, f2;     /* Original file content */
dbda8d6ce9 2007-07-21       drh:   Blob d12, d21;   /* Deltas from f1->f2 and f2->f1 */
dbda8d6ce9 2007-07-21       drh:   Blob a1, a2;     /* Recovered file content */
dbda8d6ce9 2007-07-21       drh:   if( g.argc!=4 ) usage("FILE1 FILE2");
dbda8d6ce9 2007-07-21       drh:   blob_read_from_file(&f1, g.argv[2]);
dbda8d6ce9 2007-07-21       drh:   blob_read_from_file(&f2, g.argv[3]);
dbda8d6ce9 2007-07-21       drh:   blob_delta_create(&f1, &f2, &d12);
dbda8d6ce9 2007-07-21       drh:   blob_delta_create(&f2, &f1, &d21);
dbda8d6ce9 2007-07-21       drh:   blob_delta_apply(&f1, &d12, &a2);
dbda8d6ce9 2007-07-21       drh:   blob_delta_apply(&f2, &d21, &a1);
dbda8d6ce9 2007-07-21       drh:   if( blob_compare(&f1,&a1) || blob_compare(&f2, &a2) ){
dbda8d6ce9 2007-07-21       drh:     fossil_panic("delta test failed");
dbda8d6ce9 2007-07-21       drh:   }
dbda8d6ce9 2007-07-21       drh:   printf("ok\n");
dbda8d6ce9 2007-07-21       drh: }