587
588
589
590
591
592
593
594
595
596
597
598
599
600
|
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
|
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
|
#endif
if( total!=limit ){
/* ERROR: generated size does not match predicted size */
return -1;
}
return total;
}
default: {
/* ERROR: unknown delta operator */
return -1;
}
}
}
/* ERROR: unterminated delta */
return -1;
}
/*
** Analyze a delta. Figure out the total number of bytes copied from
** source to target, and the total number of bytes inserted by the delta,
** and return both numbers.
*/
int delta_analyze(
const char *zDelta, /* Delta to apply to the pattern */
int lenDelta, /* Length of the delta */
int *pnCopy, /* OUT: Number of bytes copied */
int *pnInsert /* OUT: Number of bytes inserted */
){
unsigned int nInsert = 0;
unsigned int nCopy = 0;
(void)getInt(&zDelta, &lenDelta);
if( *zDelta!='\n' ){
/* ERROR: size integer not terminated by "\n" */
return -1;
}
zDelta++; lenDelta--;
while( *zDelta && lenDelta>0 ){
unsigned int cnt, ofst;
cnt = getInt(&zDelta, &lenDelta);
switch( zDelta[0] ){
case '@': {
zDelta++; lenDelta--;
ofst = getInt(&zDelta, &lenDelta);
if( lenDelta>0 && zDelta[0]!=',' ){
/* ERROR: copy command not terminated by ',' */
return -1;
}
zDelta++; lenDelta--;
nCopy += cnt;
break;
}
case ':': {
zDelta++; lenDelta--;
nInsert += cnt;
if( cnt>lenDelta ){
/* ERROR: insert count exceeds size of delta */
return -1;
}
zDelta += cnt;
lenDelta -= cnt;
break;
}
case ';': {
*pnCopy = nCopy;
*pnInsert = nInsert;
return 0;
}
default: {
/* ERROR: unknown delta operator */
return -1;
}
}
}
/* ERROR: unterminated delta */
|