Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
att
GitHub Repository: att/ast
Path: blob/master/src/lib/libvdelta/vd01/vdupdate01.c
1810 views
1
/***********************************************************************
2
* *
3
* This software is part of the ast package *
4
* Copyright (c) 1995-2011 AT&T Intellectual Property *
5
* and is licensed under the *
6
* Eclipse Public License, Version 1.0 *
7
* by AT&T Intellectual Property *
8
* *
9
* A copy of the License is available at *
10
* http://www.eclipse.org/org/documents/epl-v10.html *
11
* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
12
* *
13
* Information and Software Systems Research *
14
* AT&T Research *
15
* Florham Park NJ *
16
* *
17
* Phong Vo <[email protected]> *
18
* *
19
***********************************************************************/
20
#include "vdelhdr01.h"
21
22
23
/* Apply the transformation source->target to reconstruct target
24
** This code is designed to work even if the local machine has
25
** word size smaller than that of the machine where the delta
26
** was computed. A requirement is that "long" on the local
27
** machine must be large enough to hold source and target sizes.
28
** It is also assumed that if an array is given, the size of
29
** that array in bytes must be storable in an "int". This is
30
** used in various cast from "long" to "int".
31
**
32
** Written by (Kiem-)Phong Vo, [email protected], 5/20/94
33
*/
34
typedef struct _table_s
35
{ Vdio_t io; /* io structure */
36
Vddisc_t* source; /* source data discipline */
37
Vddisc_t* target; /* target data discipline */
38
uchar* src; /* source string */
39
long n_src;
40
uchar* tar; /* target string */
41
long n_tar;
42
long s_org; /* start of window in source */
43
long t_org; /* start of window in target */
44
uchar data[128]; /* buffer for data transferring */
45
char s_alloc; /* 1 if source was allocated */
46
char t_alloc; /* 1 if target was allocated */
47
char compress; /* 1 if compressing only */
48
K_UDECL(quick,recent,rhere); /* address caches */
49
} Table_t;
50
51
#if __STD_C
52
static int vdunfold(Table_t* tab)
53
#else
54
static int vdunfold(tab)
55
Table_t* tab;
56
#endif
57
{
58
reg long size, copy;
59
reg int inst, k_type, n, r;
60
reg uchar *tar, *src, *to, *fr;
61
reg long t, c_addr, n_tar, n_src;
62
reg Vddisc_t *target, *source;
63
64
n_tar = tab->n_tar;
65
tar = tab->tar;
66
n_src = tab->n_src;
67
src = tab->src;
68
target = tab->target;
69
source = tab->source;
70
71
for(t = 0, c_addr = n_src; t < n_tar; )
72
{ if((inst = VDGETC((Vdio_t*)tab)) < 0)
73
return -1;
74
k_type = K_GET(inst);
75
76
if(!VD_ISCOPY(k_type))
77
{ if(K_ISMERGE(k_type)) /* merge/add instruction */
78
size = A_TGET(inst);
79
else if(A_ISHERE(inst)) /* locally coded ADD size */
80
size = A_LGET(inst);
81
else /* non-local ADD size */
82
{ if((size = VDGETC((Vdio_t*)tab)) < 0)
83
return -1;
84
if(size >= I_MORE &&
85
(size = (long)(*_Vdgetu)((Vdio_t*)tab,size)) < 0)
86
return -1;
87
size = A_GET(size);
88
}
89
if((t+size) > n_tar) /* out of sync */
90
return -1;
91
c_addr += size;
92
93
/* copy data from the delta stream to target */
94
for(;;)
95
{ if(!tar)
96
{ if((long)(n = sizeof(tab->data)) > size)
97
n = (int)size;
98
if((*_Vdread)((Vdio_t*)tab,tab->data,n) != n )
99
return -1;
100
r = (*target->writef)((Void_t*)tab->data, n,
101
tab->t_org+t, target);
102
if(r != n)
103
return -1;
104
}
105
else
106
{ n = (int)size;
107
if((*_Vdread)((Vdio_t*)tab,tar+t,n) != n)
108
return -1;
109
}
110
t += n;
111
if((size -= n) <= 0)
112
break;
113
}
114
115
if(K_ISMERGE(k_type))
116
{ size = C_TGET(inst);
117
k_type -= K_MERGE;
118
goto do_copy;
119
}
120
}
121
else
122
{ if(C_ISHERE(inst)) /* locally coded COPY size */
123
size = C_LGET(inst);
124
else
125
{ if((size = VDGETC((Vdio_t*)tab)) < 0)
126
return -1;
127
if(size >= I_MORE &&
128
(size = (long)(*_Vdgetu)((Vdio_t*)tab,size)) < 0)
129
return -1;
130
size = C_GET(size);
131
}
132
do_copy:
133
if((t+size) > n_tar) /* out of sync */
134
return -1;
135
136
if((copy = VDGETC((Vdio_t*)tab)) < 0)
137
return -1;
138
if(k_type >= K_QUICK && k_type < (K_QUICK+K_QTYPE) )
139
copy = tab->quick[copy + ((k_type-K_QUICK)<<VD_BITS)];
140
else
141
{ if(copy >= I_MORE &&
142
(copy = (long)(*_Vdgetu)((Vdio_t*)tab,copy)) < 0)
143
return -1;
144
if(k_type >= K_RECENT && k_type < (K_RECENT+K_RTYPE) )
145
copy += tab->recent[k_type - K_RECENT];
146
else if(k_type == K_HERE)
147
copy = c_addr - copy;
148
/* else k_type == K_SELF */
149
}
150
K_UPDATE(tab->quick,tab->recent,tab->rhere,copy);
151
c_addr += size;
152
153
if(copy < n_src) /* copy from source data */
154
{ if((copy+size) > n_src) /* out of sync */
155
return -1;
156
if(src)
157
{ n = (int)size;
158
fr = src+copy;
159
if(tar)
160
{ to = tar+t;
161
MEMCPY(to,fr,n);
162
}
163
else
164
{ r = (*target->writef)((Void_t*)fr, n,
165
tab->t_org+t, target);
166
if(r != n)
167
return -1;
168
}
169
t += n;
170
}
171
else
172
{ reg Vddisc_t* disc;
173
174
if(tab->compress)
175
{ copy += tab->t_org - tab->n_src;
176
disc = target;
177
}
178
else
179
{ copy += tab->s_org;
180
disc = source;
181
}
182
for(;;)
183
{ if(tar)
184
{ n = (int)size;
185
r = (*disc->readf)
186
((Void_t*)(tar+t), n,
187
copy, disc );
188
}
189
else
190
{ n = sizeof(tab->data);
191
if((long)n > size)
192
n = (int)size;
193
r = (*disc->readf)
194
((Void_t*)tab->data, n,
195
copy, disc );
196
if(r != n)
197
return -1;
198
r = (*target->writef)
199
((Void_t*)tab->data, n,
200
tab->t_org+t, target);
201
}
202
if(r != n)
203
return -1;
204
t += n;
205
if((size -= n) <= 0)
206
break;
207
copy += n;
208
}
209
}
210
}
211
else /* copy from target data */
212
{ copy -= n_src;
213
if(copy >= t || (copy+size) > n_tar) /* out-of-sync */
214
return -1;
215
for(;;) /* allow for copying overlapped data */
216
{ reg long s, a;
217
if((s = t-copy) > size)
218
s = size;
219
if(tar)
220
{ to = tar+t; fr = tar+copy; n = (int)s;
221
MEMCPY(to,fr,n);
222
t += n;
223
goto next;
224
}
225
226
/* hard read/write */
227
a = copy;
228
for(;;)
229
{ if((long)(n = sizeof(tab->data)) > s)
230
n = (int)s;
231
r = (*target->readf)
232
((Void_t*)tab->data, n,
233
a + tab->t_org, target );
234
if(r != n)
235
return -1;
236
r = (*target->writef)
237
((Void_t*)tab->data, n,
238
t + tab->t_org, target );
239
if(r != n)
240
return -1;
241
t += n;
242
if((s -= n) <= 0)
243
break;
244
a += n;
245
}
246
247
next: if((size -= s) == 0)
248
break;
249
}
250
}
251
}
252
}
253
254
return 0;
255
}
256
257
#if __STD_C
258
long _vdupdate_01(Vddisc_t* source, Vddisc_t* target, Vddisc_t* delta)
259
#else
260
long _vdupdate_01(source,target,delta)
261
Vddisc_t* source; /* source data */
262
Vddisc_t* target; /* target data */
263
Vddisc_t* delta; /* delta data */
264
#endif
265
{
266
reg int n, r;
267
reg uchar *tar, *src;
268
reg long t, p, window, n_src, n_tar;
269
reg uchar *data;
270
uchar magic[8];
271
Table_t tab;
272
273
if(!target || (!target->data && !target->writef) )
274
return -1;
275
if(!delta || (!delta->data && !delta->readf) )
276
return -1;
277
278
/* initialize I/O buffer */
279
INIT(&tab.io,delta);
280
tab.source = source;
281
tab.target = target;
282
283
/* check magic header */
284
data = (uchar*)(VD_MAGIC);
285
for(n = 0; data[n]; ++n)
286
;
287
if((*_Vdread)(&tab.io,magic,n) != n)
288
return -1;
289
for(n -= 1; n >= 0; --n)
290
if(data[n] != magic[n])
291
return -1;
292
293
/* get true target size */
294
if((t = (long)(*_Vdgetu)(&tab.io,0)) < 0 ||
295
(target->data && target->size < t) )
296
return -1;
297
n_tar = t;
298
299
/* get true source size */
300
if((t = (long)(*_Vdgetu)(&tab.io,0)) < 0)
301
return -1;
302
else if(t > 0)
303
{ if(!source || (!source->data && !source->readf) )
304
return -1;
305
if(source->data && source->size < t)
306
return -1;
307
}
308
n_src = t;
309
310
/* get window size */
311
if((window = (long)(*_Vdgetu)(&tab.io,0)) < 0)
312
return -1;
313
314
tab.compress = n_src == 0 ? 1 : 0;
315
316
/* if we have space, it'll be faster to unfold */
317
tab.tar = tab.src = NIL(uchar*);
318
tab.t_alloc = tab.s_alloc = 0;
319
320
if(n_tar > 0 && !target->data && window < (long)MAXINT)
321
n = (int)window;
322
else n = 0;
323
if(n > 0 && (tab.tar = (uchar*)malloc(n*sizeof(uchar))) )
324
tab.t_alloc = 1;
325
326
if(n_src > 0 && !source->data && window < (long)MAXINT)
327
n = (int)window;
328
else if(n_src == 0 && window < n_tar && !target->data &&
329
HEADER(window) < (long)MAXINT)
330
n = (int)HEADER(window);
331
else n = 0;
332
if(n > 0 && (tab.src = (uchar*)malloc(n*sizeof(uchar))) )
333
tab.s_alloc = 1;
334
335
tar = (uchar*)target->data;
336
src = (uchar*)(source ? source->data : NIL(Void_t*));
337
for(t = 0; t < n_tar; )
338
{ tab.t_org = t; /* current location in target stream */
339
340
if(n_src == 0) /* data compression */
341
{ tab.s_org = 0;
342
343
if(t == 0)
344
tab.n_src = 0;
345
else
346
{ tab.n_src = HEADER(window);
347
p = t - tab.n_src;
348
if(tar)
349
tab.src = tar + p;
350
else if(tab.src)
351
{ n = (int)tab.n_src;
352
if(tab.tar)
353
{ data = tab.tar + tab.n_tar - n;
354
memcpy((Void_t*)tab.src,(Void_t*)data,n);
355
}
356
else
357
{ r = (*target->readf)(tab.src,n,p,target);
358
if(r != n)
359
goto done;
360
}
361
}
362
}
363
}
364
else /* data differencing */
365
{ tab.n_src = window;
366
if(t < n_src)
367
{ if((t+window) > n_src)
368
p = n_src-window;
369
else p = t;
370
371
tab.s_org = p;
372
373
if(src)
374
tab.src = src + p;
375
else if(tab.src)
376
{ n = (int)tab.n_src;
377
r = (*source->readf)(tab.src,n,p,source);
378
if(r != n)
379
goto done;
380
}
381
}
382
}
383
384
if(tar)
385
tab.tar = (uchar*)tar+t;
386
tab.n_tar = window < (n_tar-t) ? window : (n_tar-t);
387
388
K_INIT(tab.quick,tab.recent,tab.rhere);
389
if(vdunfold(&tab) < 0)
390
goto done;
391
if(!target->data && tab.tar)
392
{ p = (*target->writef)((Void_t*)tab.tar,(int)tab.n_tar,t,target);
393
if(p != tab.n_tar)
394
goto done;
395
}
396
397
t += tab.n_tar;
398
}
399
400
done:
401
if(tab.t_alloc)
402
free((Void_t*)tab.tar);
403
if(tab.s_alloc)
404
free((Void_t*)tab.src);
405
406
return t;
407
}
408
409