Skip to content

Commit 24cfeb1

Browse files
committed
first commit
0 parents  commit 24cfeb1

10 files changed

+1008
-0
lines changed

.gitignore

+42
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
*.dep
2+
*.lo
3+
*.la
4+
.libs
5+
acinclude.m4
6+
aclocal.m4
7+
autom4te.cache
8+
build
9+
config.guess
10+
config.h
11+
config.h.in
12+
config.log
13+
config.nice
14+
config.status
15+
config.sub
16+
configure
17+
configure.ac
18+
configure.in
19+
include
20+
install-sh
21+
libtool
22+
ltmain.sh
23+
Makefile
24+
Makefile.fragments
25+
Makefile.global
26+
Makefile.objects
27+
missing
28+
mkinstalldirs
29+
modules
30+
php_test_results_*.txt
31+
phpt.*
32+
run-test-info.php
33+
run-tests.php
34+
tests/**/*.diff
35+
tests/**/*.out
36+
tests/**/*.php
37+
tests/**/*.exp
38+
tests/**/*.log
39+
tests/**/*.sh
40+
tests/**/*.db
41+
tests/**/*.mem
42+
tmp-php.ini

bsdiff.c

+350
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,350 @@
1+
/*-
2+
* Copyright 2003-2005 Colin Percival
3+
* Copyright 2012 Matthew Endsley
4+
* All rights reserved
5+
*
6+
* Redistribution and use in source and binary forms, with or without
7+
* modification, are permitted providing that the following conditions
8+
* are met:
9+
* 1. Redistributions of source code must retain the above copyright
10+
* notice, this list of conditions and the following disclaimer.
11+
* 2. Redistributions in binary form must reproduce the above copyright
12+
* notice, this list of conditions and the following disclaimer in the
13+
* documentation and/or other materials provided with the distribution.
14+
*
15+
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16+
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17+
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18+
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
19+
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20+
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21+
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22+
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
23+
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
24+
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25+
* POSSIBILITY OF SUCH DAMAGE.
26+
*/
27+
28+
#include "bsdiff.h"
29+
30+
#include <limits.h>
31+
#include <string.h>
32+
33+
#define MIN(x,y) (((x)<(y)) ? (x) : (y))
34+
35+
static void split(int64_t *I,int64_t *V,int64_t start,int64_t len,int64_t h)
36+
{
37+
int64_t i,j,k,x,tmp,jj,kk;
38+
39+
if(len<16) {
40+
for(k=start;k<start+len;k+=j) {
41+
j=1;x=V[I[k]+h];
42+
for(i=1;k+i<start+len;i++) {
43+
if(V[I[k+i]+h]<x) {
44+
x=V[I[k+i]+h];
45+
j=0;
46+
};
47+
if(V[I[k+i]+h]==x) {
48+
tmp=I[k+j];I[k+j]=I[k+i];I[k+i]=tmp;
49+
j++;
50+
};
51+
};
52+
for(i=0;i<j;i++) V[I[k+i]]=k+j-1;
53+
if(j==1) I[k]=-1;
54+
};
55+
return;
56+
};
57+
58+
x=V[I[start+len/2]+h];
59+
jj=0;kk=0;
60+
for(i=start;i<start+len;i++) {
61+
if(V[I[i]+h]<x) jj++;
62+
if(V[I[i]+h]==x) kk++;
63+
};
64+
jj+=start;kk+=jj;
65+
66+
i=start;j=0;k=0;
67+
while(i<jj) {
68+
if(V[I[i]+h]<x) {
69+
i++;
70+
} else if(V[I[i]+h]==x) {
71+
tmp=I[i];I[i]=I[jj+j];I[jj+j]=tmp;
72+
j++;
73+
} else {
74+
tmp=I[i];I[i]=I[kk+k];I[kk+k]=tmp;
75+
k++;
76+
};
77+
};
78+
79+
while(jj+j<kk) {
80+
if(V[I[jj+j]+h]==x) {
81+
j++;
82+
} else {
83+
tmp=I[jj+j];I[jj+j]=I[kk+k];I[kk+k]=tmp;
84+
k++;
85+
};
86+
};
87+
88+
if(jj>start) split(I,V,start,jj-start,h);
89+
90+
for(i=0;i<kk-jj;i++) V[I[jj+i]]=kk-1;
91+
if(jj==kk-1) I[jj]=-1;
92+
93+
if(start+len>kk) split(I,V,kk,start+len-kk,h);
94+
}
95+
96+
static void qsufsort(int64_t *I,int64_t *V,const uint8_t *old,int64_t oldsize)
97+
{
98+
int64_t buckets[256];
99+
int64_t i,h,len;
100+
101+
for(i=0;i<256;i++) buckets[i]=0;
102+
for(i=0;i<oldsize;i++) buckets[old[i]]++;
103+
for(i=1;i<256;i++) buckets[i]+=buckets[i-1];
104+
for(i=255;i>0;i--) buckets[i]=buckets[i-1];
105+
buckets[0]=0;
106+
107+
for(i=0;i<oldsize;i++) I[++buckets[old[i]]]=i;
108+
I[0]=oldsize;
109+
for(i=0;i<oldsize;i++) V[i]=buckets[old[i]];
110+
V[oldsize]=0;
111+
for(i=1;i<256;i++) if(buckets[i]==buckets[i-1]+1) I[buckets[i]]=-1;
112+
I[0]=-1;
113+
114+
for(h=1;I[0]!=-(oldsize+1);h+=h) {
115+
len=0;
116+
for(i=0;i<oldsize+1;) {
117+
if(I[i]<0) {
118+
len-=I[i];
119+
i-=I[i];
120+
} else {
121+
if(len) I[i-len]=-len;
122+
len=V[I[i]]+1-i;
123+
split(I,V,i,len,h);
124+
i+=len;
125+
len=0;
126+
};
127+
};
128+
if(len) I[i-len]=-len;
129+
};
130+
131+
for(i=0;i<oldsize+1;i++) I[V[i]]=i;
132+
}
133+
134+
static int64_t matchlen(const uint8_t *old,int64_t oldsize,const uint8_t *new,int64_t newsize)
135+
{
136+
int64_t i;
137+
138+
for(i=0;(i<oldsize)&&(i<newsize);i++)
139+
if(old[i]!=new[i]) break;
140+
141+
return i;
142+
}
143+
144+
static int64_t search(const int64_t *I,const uint8_t *old,int64_t oldsize,
145+
const uint8_t *new,int64_t newsize,int64_t st,int64_t en,int64_t *pos)
146+
{
147+
int64_t x,y;
148+
149+
if(en-st<2) {
150+
x=matchlen(old+I[st],oldsize-I[st],new,newsize);
151+
y=matchlen(old+I[en],oldsize-I[en],new,newsize);
152+
153+
if(x>y) {
154+
*pos=I[st];
155+
return x;
156+
} else {
157+
*pos=I[en];
158+
return y;
159+
}
160+
};
161+
162+
x=st+(en-st)/2;
163+
if(memcmp(old+I[x],new,MIN(oldsize-I[x],newsize))<0) {
164+
return search(I,old,oldsize,new,newsize,x,en,pos);
165+
} else {
166+
return search(I,old,oldsize,new,newsize,st,x,pos);
167+
};
168+
}
169+
170+
void offtout(int64_t x,uint8_t *buf)
171+
{
172+
int64_t y;
173+
174+
if(x<0) y=-x; else y=x;
175+
176+
buf[0]=y%256;y-=buf[0];
177+
y=y/256;buf[1]=y%256;y-=buf[1];
178+
y=y/256;buf[2]=y%256;y-=buf[2];
179+
y=y/256;buf[3]=y%256;y-=buf[3];
180+
y=y/256;buf[4]=y%256;y-=buf[4];
181+
y=y/256;buf[5]=y%256;y-=buf[5];
182+
y=y/256;buf[6]=y%256;y-=buf[6];
183+
y=y/256;buf[7]=y%256;
184+
185+
if(x<0) buf[7]|=0x80;
186+
}
187+
188+
static int64_t writedata(struct bsdiff_stream* stream, const void* buffer, int64_t length)
189+
{
190+
int64_t result = 0;
191+
192+
while (length > 0)
193+
{
194+
const int smallsize = (int)MIN(length, INT_MAX);
195+
const int writeresult = stream->write(stream, buffer, smallsize);
196+
if (writeresult == -1)
197+
{
198+
return -1;
199+
}
200+
201+
result += writeresult;
202+
length -= smallsize;
203+
buffer = (uint8_t*)buffer + smallsize;
204+
}
205+
206+
return result;
207+
}
208+
209+
struct bsdiff_request
210+
{
211+
const uint8_t* old;
212+
int64_t oldsize;
213+
const uint8_t* new;
214+
int64_t newsize;
215+
struct bsdiff_stream* stream;
216+
int64_t *I;
217+
uint8_t *buffer;
218+
};
219+
220+
static int bsdiff_internal(const struct bsdiff_request req)
221+
{
222+
int64_t *I,*V;
223+
int64_t scan,pos,len;
224+
int64_t lastscan,lastpos,lastoffset;
225+
int64_t oldscore,scsc;
226+
int64_t s,Sf,lenf,Sb,lenb;
227+
int64_t overlap,Ss,lens;
228+
int64_t i;
229+
uint8_t *buffer;
230+
uint8_t buf[8 * 3];
231+
232+
if((V=req.stream->malloc((req.oldsize+1)*sizeof(int64_t)))==NULL) return -1;
233+
I = req.I;
234+
235+
qsufsort(I,V,req.old,req.oldsize);
236+
req.stream->free(V);
237+
238+
buffer = req.buffer;
239+
240+
/* Compute the differences, writing ctrl as we go */
241+
scan=0;len=0;pos=0;
242+
lastscan=0;lastpos=0;lastoffset=0;
243+
while(scan<req.newsize) {
244+
oldscore=0;
245+
246+
for(scsc=scan+=len;scan<req.newsize;scan++) {
247+
len=search(I,req.old,req.oldsize,req.new+scan,req.newsize-scan,
248+
0,req.oldsize,&pos);
249+
250+
for(;scsc<scan+len;scsc++)
251+
if((scsc+lastoffset<req.oldsize) &&
252+
(req.old[scsc+lastoffset] == req.new[scsc]))
253+
oldscore++;
254+
255+
if(((len==oldscore) && (len!=0)) ||
256+
(len>oldscore+8)) break;
257+
258+
if((scan+lastoffset<req.oldsize) &&
259+
(req.old[scan+lastoffset] == req.new[scan]))
260+
oldscore--;
261+
};
262+
263+
if((len!=oldscore) || (scan==req.newsize)) {
264+
s=0;Sf=0;lenf=0;
265+
for(i=0;(lastscan+i<scan)&&(lastpos+i<req.oldsize);) {
266+
if(req.old[lastpos+i]==req.new[lastscan+i]) s++;
267+
i++;
268+
if(s*2-i>Sf*2-lenf) { Sf=s; lenf=i; };
269+
};
270+
271+
lenb=0;
272+
if(scan<req.newsize) {
273+
s=0;Sb=0;
274+
for(i=1;(scan>=lastscan+i)&&(pos>=i);i++) {
275+
if(req.old[pos-i]==req.new[scan-i]) s++;
276+
if(s*2-i>Sb*2-lenb) { Sb=s; lenb=i; };
277+
};
278+
};
279+
280+
if(lastscan+lenf>scan-lenb) {
281+
overlap=(lastscan+lenf)-(scan-lenb);
282+
s=0;Ss=0;lens=0;
283+
for(i=0;i<overlap;i++) {
284+
if(req.new[lastscan+lenf-overlap+i]==
285+
req.old[lastpos+lenf-overlap+i]) s++;
286+
if(req.new[scan-lenb+i]==
287+
req.old[pos-lenb+i]) s--;
288+
if(s>Ss) { Ss=s; lens=i+1; };
289+
};
290+
291+
lenf+=lens-overlap;
292+
lenb-=lens;
293+
};
294+
295+
offtout(lenf,buf);
296+
offtout((scan-lenb)-(lastscan+lenf),buf+8);
297+
offtout((pos-lenb)-(lastpos+lenf),buf+16);
298+
299+
/* Write control data */
300+
if (writedata(req.stream, buf, sizeof(buf)))
301+
return -1;
302+
303+
/* Write diff data */
304+
for(i=0;i<lenf;i++)
305+
buffer[i]=req.new[lastscan+i]-req.old[lastpos+i];
306+
if (writedata(req.stream, buffer, lenf))
307+
return -1;
308+
309+
/* Write extra data */
310+
for(i=0;i<(scan-lenb)-(lastscan+lenf);i++)
311+
buffer[i]=req.new[lastscan+lenf+i];
312+
if (writedata(req.stream, buffer, (scan-lenb)-(lastscan+lenf)))
313+
return -1;
314+
315+
lastscan=scan-lenb;
316+
lastpos=pos-lenb;
317+
lastoffset=pos-scan;
318+
};
319+
};
320+
321+
return 0;
322+
}
323+
324+
int bsdiff(const uint8_t* old, int64_t oldsize, const uint8_t* new, int64_t newsize, struct bsdiff_stream* stream)
325+
{
326+
int result;
327+
struct bsdiff_request req;
328+
329+
if((req.I=stream->malloc((oldsize+1)*sizeof(int64_t)))==NULL)
330+
return -1;
331+
332+
if((req.buffer=stream->malloc(newsize+1))==NULL)
333+
{
334+
stream->free(req.I);
335+
return -1;
336+
}
337+
338+
req.old = old;
339+
req.oldsize = oldsize;
340+
req.new = new;
341+
req.newsize = newsize;
342+
req.stream = stream;
343+
344+
result = bsdiff_internal(req);
345+
346+
stream->free(req.buffer);
347+
stream->free(req.I);
348+
349+
return result;
350+
}

0 commit comments

Comments
 (0)