1 | #include<stdio.h> |
2 | #include<stdlib.h> |
3 | #include<string.h> |
4 | #include<math.h> |
5 | #include<stdint.h> |
6 | #include<string> |
7 | using std::string; |
8 | typedef uint8_t U8; |
9 | typedef uint16_t U16; |
10 | typedef uint32_t U32; |
11 | typedef uint64_t U64; |
12 | template<typename T> |
13 | struct Array{ |
14 | T*data; |
15 | size_t n; |
16 | Array(size_t sz=0,int ex=0):data(0),n(0){ |
17 | resize(sz,ex); |
18 | } |
19 | void resize(size_t sz,int ex=0); |
20 | ~Array(){ |
21 | resize(0); |
22 | } |
23 | size_t size(){ |
24 | return n; |
25 | } |
26 | T&operator[](size_t i){ |
27 | return data[i]; |
28 | } |
29 | T&operator()(size_t i){ |
30 | return data[i&(n-1)]; |
31 | } |
32 | } |
33 | ; |
34 | template<typename T> |
35 | void Array<T>::resize(size_t sz,int ex){ |
36 | if(n>0)free((char*)data); |
37 | n=0; |
38 | if(sz==0)return; |
39 | n=sz<<ex; |
40 | const size_t nb=128+n*sizeof(T); |
41 | data=(T*)calloc(nb,1); |
42 | } |
43 | typedef enum{ |
44 | NONE,CONS,CM,ICM,MATCH,AVG,MIX2,MIX,ISSE,SSE} |
45 | CompType; |
46 | const int compsize[256]={ |
47 | 0,2,3,2,3,4,6,6,3,5} |
48 | ; |
49 | struct ZP{ |
50 | ZP(){ |
51 | out=0; |
52 | clear(); |
53 | } |
54 | void clear(); |
55 | void run(U32 input){ |
56 | pc=hbegin; |
57 | a=input; |
58 | while(execute()); |
59 | } |
60 | int read(FILE*in2); |
61 | FILE*out; |
62 | Array<U8>hd,m; |
63 | Array<U32>h,r; |
64 | int cend,hbegin,hend,f,pc; |
65 | U32 a,b,c,d; |
66 | void init(int hbits,int mbits); |
67 | int execute(); |
68 | void div(U32 x){ |
69 | if(x)a/=x; |
70 | else a=0; |
71 | } |
72 | void mod(U32 x){ |
73 | if(x)a%=x; |
74 | else a=0; |
75 | } |
76 | void swap(U32&x){ |
77 | a^=x; |
78 | x^=a; |
79 | a^=x; |
80 | } |
81 | void swap(U8&x){ |
82 | a^=x; |
83 | x^=a; |
84 | a^=x; |
85 | } |
86 | } |
87 | ; |
88 | int ZP::read(FILE*in2){ |
89 | int hsize=getc(in2); |
90 | hsize+=getc(in2)*256; |
91 | hd.resize(hsize+300); |
92 | cend=hbegin=hend=0; |
93 | hd[cend++]=hsize&255; |
94 | hd[cend++]=hsize>>8; |
95 | while(cend<7)hd[cend++]=getc(in2); |
96 | int n=hd[cend-1]; |
97 | for(int i=0;i<n;++i){ |
98 | int type=getc(in2); |
99 | hd[cend++]=type; |
100 | int size=compsize[type]; |
101 | for(int j=1;j<size;++j) |
102 | hd[cend++]=getc(in2); |
103 | } |
104 | hd[cend++]=getc(in2); |
105 | hbegin=hend=cend+128; |
106 | while(hend<hsize+129){ |
107 | int op=getc(in2); |
108 | hd[hend++]=op; |
109 | } |
110 | hd[hend++]=getc(in2); |
111 | return cend+hend-hbegin; |
112 | } |
113 | void ZP::clear(){ |
114 | cend=hbegin=hend=0; |
115 | hd.resize(0); |
116 | a=b=c=d=f=pc=0; |
117 | h.resize(0); |
118 | m.resize(0); |
119 | r.resize(0); |
120 | } |
121 | void ZP::init(int hbits,int mbits){ |
122 | a=b=c=d=f=pc=0; |
123 | h.resize(1,hbits); |
124 | m.resize(1,mbits); |
125 | r.resize(256); |
126 | } |
127 | #define C(i,L,R)\ |
128 | case i:L(a R);break;\ |
129 | case i+1:L(b R);break;\ |
130 | case i+2:L(c R);break;\ |
131 | case i+3:L(d R);break;\ |
132 | case i+4:L(U32(m(b))R);break;\ |
133 | case i+5:L(U32(m(c))R);break;\ |
134 | case i+6:L(h(d) R);break;\ |
135 | case i+7:L(U32(hd[pc++])R);break; |
136 | #define C1(i,x)\ |
137 | case i:swap(x);break;\ |
138 | case i+1:++x;break;\ |
139 | case i+2:--x;break;\ |
140 | case i+3:x=~x;break;\ |
141 | case i+4:x=0;break; |
142 | int ZP::execute(){ |
143 | switch(hd[pc++]){ |
144 | case 7:a=r[hd[pc++]];break; |
145 | case 15:b=r[hd[pc++]];break; |
146 | case 23:c=r[hd[pc++]];break; |
147 | case 31:d=r[hd[pc++]];break; |
148 | case 39:if(f)pc+=((hd[pc]+128)&255)-127;else ++pc;break; |
149 | case 47:if(!f)pc+=((hd[pc]+128)&255)-127;else ++pc;break; |
150 | case 55:r[hd[pc++]]=a;break; |
151 | case 56:return 0; |
152 | case 57:if(out)putc(a,out);break; |
153 | case 59:a=(a+m(b)+512)*773;break; |
154 | case 60:h(d)=(h(d)+a+512)*773;break; |
155 | case 63:pc+=((hd[pc]+128)&255)-127;break; |
156 | C1(0,a) |
157 | C1(8,b) |
158 | C1(16,c) |
159 | C1(24,d) |
160 | C1(32,m(b)) |
161 | C1(40,m(c)) |
162 | C1(48,h(d)) |
163 | C(64,a=,) |
164 | C(72,b=,) |
165 | C(80,c=,) |
166 | C(88,d=,) |
167 | C(96,m(b)=,) |
168 | C(104,m(c)=,) |
169 | C(112,h(d)=,) |
170 | C(128,a+=,) |
171 | C(136,a-=,) |
172 | C(144,a*=,) |
173 | C(152,div,) |
174 | C(160,mod,) |
175 | C(168,a&=,) |
176 | C(176,a&= ~,) |
177 | C(184,a|=,) |
178 | C(192,a^=,) |
179 | C(200,a<<=,&31) |
180 | C(208,a>>=,&31) |
181 | C(216,f=,==a) |
182 | C(224,f=,>a) |
183 | C(232,f=,<a) |
184 | } |
185 | return 1; |
186 | } |
187 | struct CP{ |
188 | U32 limit,cxt,a,b,c; |
189 | Array<U32>cm; |
190 | Array<U8>ht; |
191 | Array<U16>a16; |
192 | void init(); |
193 | CP(){ |
194 | init(); |
195 | } |
196 | } |
197 | ; |
198 | void CP::init(){ |
199 | limit=cxt=a=b=c=0; |
200 | cm.resize(0); |
201 | ht.resize(0); |
202 | a16.resize(0); |
203 | } |
204 | struct ST{ |
205 | enum{ |
206 | N=64} |
207 | ; |
208 | int nns(int n0,int n1); |
209 | void ds(int&n0); |
210 | void nx(int&n0,int&n1,int y); |
211 | U8 ns[1024]; |
212 | int cminit(int state){ |
213 | return((ns[state*4+3]*2+1)<<22)/(ns[state*4+2]+ns[state*4+3]+1); |
214 | } |
215 | ST(); |
216 | } |
217 | ; |
218 | int ST::nns(int n0,int n1){ |
219 | const int B=6,bound[B]={ |
220 | 20,48,15,8,6,5} |
221 | ; |
222 | if(n0<n1)return nns(n1,n0); |
223 | if(n0<0||n1<0||n1>=B||n0>bound[n1])return 0; |
224 | return 1+(n1>0&&n0+n1<=17); |
225 | } |
226 | void ST::ds(int&n0){ |
227 | n0=(n0>=1)+(n0>=2)+(n0>=3)+(n0>=4)+(n0>=5)+(n0>=7)+(n0>=8); |
228 | } |
229 | void ST::nx(int&n0,int&n1,int y){ |
230 | if(n0<n1) |
231 | nx(n1,n0,1-y); |
232 | else{ |
233 | if(y){ |
234 | ++n1; |
235 | ds(n0); |
236 | } |
237 | else{ |
238 | ++n0; |
239 | ds(n1); |
240 | } |
241 | while(!nns(n0,n1)){ |
242 | if(n1<2)--n0; |
243 | else{ |
244 | n0=(n0*(n1-1)+(n1/2))/n1; |
245 | --n1; |
246 | } |
247 | } |
248 | } |
249 | } |
250 | ST::ST(){ |
251 | const int N=50; |
252 | U8 t[N][N][2]={ |
253 | { |
254 | { |
255 | 0} |
256 | } |
257 | } |
258 | ; |
259 | int state=0; |
260 | for(int i=0;i<N;++i){ |
261 | for(int n1=0;n1<=i;++n1){ |
262 | int n0=i-n1; |
263 | int n=nns(n0,n1); |
264 | if(n){ |
265 | t[n0][n1][0]=state; |
266 | t[n0][n1][1]=state+n-1; |
267 | state+=n; |
268 | } |
269 | } |
270 | } |
271 | memset(ns,0,sizeof(ns)); |
272 | for(int n0=0;n0<N;++n0){ |
273 | for(int n1=0;n1<N;++n1){ |
274 | for(int y=0;y<nns(n0,n1);++y){ |
275 | int s=t[n0][n1][y]; |
276 | int s0=n0,s1=n1; |
277 | nx(s0,s1,0); |
278 | ns[s*4+0]=t[s0][s1][0]; |
279 | s0=n0,s1=n1; |
280 | nx(s0,s1,1); |
281 | ns[s*4+1]=t[s0][s1][1]; |
282 | ns[s*4+2]=n0; |
283 | ns[s*4+3]=n1; |
284 | } |
285 | } |
286 | } |
287 | } |
288 | struct PR{ |
289 | PR(ZP&); |
290 | void init(); |
291 | int predict(); |
292 | void update(int y); |
293 | bool im(){ |
294 | return z.hd[6]!=0; |
295 | } |
296 | int c8,hmap4,p[256]; |
297 | U32 h[256]; |
298 | ZP&z; |
299 | CP comp[256]; |
300 | int dt2k[256]; |
301 | int dt[1024]; |
302 | U16 squasht[4096]; |
303 | short stretcht[32768]; |
304 | ST st; |
305 | void train(CP&cr,int y){ |
306 | U32&pn=cr.cm(cr.cxt); |
307 | U32 count=pn&0x3ff; |
308 | int error=y*32767-(cr.cm(cr.cxt)>>17); |
309 | pn+=(error*dt[count]&-1024)+(count<cr.limit); |
310 | } |
311 | int squash(int x){ |
312 | return squasht[x+2048]; |
313 | } |
314 | int stretch(int x){ |
315 | return stretcht[x]; |
316 | } |
317 | int clamp2k(int x){ |
318 | if(x<-2048)return -2048; |
319 | else if(x>2047)return 2047; |
320 | else return x; |
321 | } |
322 | int clamp512k(int x){ |
323 | if(x<-(1<<19))return -(1<<19); |
324 | else if(x>=(1<<19))return(1<<19)-1; |
325 | else return x; |
326 | } |
327 | size_t find(Array<U8>&ht,int sizebits,U32 cxt); |
328 | } |
329 | ; |
330 | PR::PR(ZP&zr): |
331 | c8(1),hmap4(1),z(zr){ |
332 | dt2k[0]=0; |
333 | for(int i=1;i<256;++i) |
334 | dt2k[i]=2048/i; |
335 | for(int i=0;i<1024;++i) |
336 | dt[i]=(1<<17)/(i*2+3)*2; |
337 | for(int i=0;i<32768;++i) |
338 | stretcht[i]=int(log((i+0.5)/(32767.5-i))*64+0.5+100000)-100000; |
339 | for(int i=0;i<4096;++i) |
340 | squasht[i]=int(32768.0/(1+exp((i-2048)*(-1.0/64)))); |
341 | } |
342 | void PR::init(){ |
343 | z.init(z.hd[2],z.hd[3]); |
344 | for(int i=0;i<256;++i)h[i]=p[i]=0; |
345 | for(int i=0;i<256;++i)comp[i].init(); |
346 | int n=z.hd[6]; |
347 | const U8*cp=&z.hd[7]; |
348 | for(int i=0;i<n;++i){ |
349 | CP&cr=comp[i]; |
350 | switch(cp[0]){ |
351 | case CONS: |
352 | p[i]=(cp[1]-128)*4; |
353 | break; |
354 | case CM: |
355 | cr.cm.resize(1,cp[1]); |
356 | cr.limit=cp[2]*4; |
357 | for(size_t j=0;j<cr.cm.size();++j) |
358 | cr.cm[j]=0x80000000; |
359 | break; |
360 | case ICM: |
361 | cr.limit=1023; |
362 | cr.cm.resize(256); |
363 | cr.ht.resize(64,cp[1]); |
364 | for(size_t j=0;j<cr.cm.size();++j) |
365 | cr.cm[j]=st.cminit(j); |
366 | break; |
367 | case MATCH: |
368 | cr.cm.resize(1,cp[1]); |
369 | cr.ht.resize(1,cp[2]); |
370 | cr.ht(0)=1; |
371 | break; |
372 | case MIX2: |
373 | cr.c=(size_t(1)<<cp[1]); |
374 | cr.a16.resize(1,cp[1]); |
375 | for(size_t j=0;j<cr.a16.size();++j) |
376 | cr.a16[j]=32768; |
377 | break; |
378 | case MIX:{ |
379 | int m=cp[3]; |
380 | cr.c=(size_t(1)<<cp[1]); |
381 | cr.cm.resize(m,cp[1]); |
382 | for(size_t j=0;j<cr.cm.size();++j) |
383 | cr.cm[j]=65536/m; |
384 | break; |
385 | } |
386 | case ISSE: |
387 | cr.ht.resize(64,cp[1]); |
388 | cr.cm.resize(512); |
389 | for(int j=0;j<256;++j){ |
390 | cr.cm[j*2]=1<<15; |
391 | cr.cm[j*2+1]=clamp512k(stretch(st.cminit(j)>>8)<<10); |
392 | } |
393 | break; |
394 | case SSE: |
395 | cr.cm.resize(32,cp[1]); |
396 | cr.limit=cp[4]*4; |
397 | for(size_t j=0;j<cr.cm.size();++j) |
398 | cr.cm[j]=squash((j&31)*64-992)<<17|cp[3]; |
399 | break; |
400 | } |
401 | cp+=compsize[*cp]; |
402 | } |
403 | } |
404 | int PR::predict(){ |
405 | int n=z.hd[6]; |
406 | const U8*cp=&z.hd[7]; |
407 | for(int i=0;i<n;++i){ |
408 | CP&cr=comp[i]; |
409 | switch(cp[0]){ |
410 | case CM: |
411 | cr.cxt=h[i]^hmap4; |
412 | p[i]=stretch(cr.cm(cr.cxt)>>17); |
413 | break; |
414 | case ICM: |
415 | if(c8==1||(c8&0xf0)==16)cr.c=find(cr.ht,cp[1]+2,h[i]+16*c8); |
416 | cr.cxt=cr.ht[cr.c+(hmap4&15)]; |
417 | p[i]=stretch(cr.cm(cr.cxt)>>8); |
418 | break; |
419 | case MATCH: |
420 | if(cr.a==0)p[i]=0; |
421 | else{ |
422 | cr.c=(cr.ht(cr.limit-cr.b)>>(7-cr.cxt))&1; |
423 | p[i]=stretch(dt2k[cr.a]*(cr.c*-2+1)&32767); |
424 | } |
425 | break; |
426 | case AVG: |
427 | p[i]=(p[cp[1]]*cp[3]+p[cp[2]]*(256-cp[3]))>>8; |
428 | break; |
429 | case MIX2:{ |
430 | cr.cxt=((h[i]+(c8&cp[5]))&(cr.c-1)); |
431 | int w=cr.a16[cr.cxt]; |
432 | p[i]=(w*p[cp[2]]+(65536-w)*p[cp[3]])>>16; |
433 | } |
434 | break; |
435 | case MIX:{ |
436 | int m=cp[3]; |
437 | cr.cxt=h[i]+(c8&cp[5]); |
438 | cr.cxt=(cr.cxt&(cr.c-1))*m; |
439 | int*wt=(int*)&cr.cm[cr.cxt]; |
440 | p[i]=0; |
441 | for(int j=0;j<m;++j) |
442 | p[i]+=(wt[j]>>8)*p[cp[2]+j]; |
443 | p[i]=clamp2k(p[i]>>8); |
444 | } |
445 | break; |
446 | case ISSE:{ |
447 | if(c8==1||(c8&0xf0)==16) |
448 | cr.c=find(cr.ht,cp[1]+2,h[i]+16*c8); |
449 | cr.cxt=cr.ht[cr.c+(hmap4&15)]; |
450 | int*wt=(int*)&cr.cm[cr.cxt*2]; |
451 | p[i]=clamp2k((wt[0]*p[cp[2]]+wt[1]*64)>>16); |
452 | } |
453 | break; |
454 | case SSE:{ |
455 | cr.cxt=(h[i]+c8)*32; |
456 | int pq=p[cp[2]]+992; |
457 | if(pq<0)pq=0; |
458 | if(pq>1983)pq=1983; |
459 | int wt=pq&63; |
460 | pq>>=6; |
461 | cr.cxt+=pq; |
462 | p[i]=stretch(((cr.cm(cr.cxt)>>10)*(64-wt)+(cr.cm(cr.cxt+1)>>10)*wt) |
463 | >>13); |
464 | cr.cxt+=wt>>5; |
465 | } |
466 | } |
467 | cp+=compsize[cp[0]]; |
468 | } |
469 | return squash(p[n-1]); |
470 | } |
471 | void PR::update(int y){ |
472 | const U8*cp=&z.hd[7]; |
473 | int n=z.hd[6]; |
474 | for(int i=0;i<n;++i){ |
475 | CP&cr=comp[i]; |
476 | switch(cp[0]){ |
477 | case CM: |
478 | train(cr,y); |
479 | break; |
480 | case ICM:{ |
481 | cr.ht[cr.c+(hmap4&15)]=st.ns[cr.ht[cr.c+(hmap4&15)]*4+y]; |
482 | U32&pn=cr.cm(cr.cxt); |
483 | pn+=int(y*32767-(pn>>8))>>2; |
484 | } |
485 | break; |
486 | case MATCH: |
487 | { |
488 | if(int(cr.c)!=y)cr.a=0; |
489 | cr.ht(cr.limit)+=cr.ht(cr.limit)+y; |
490 | if(++cr.cxt==8){ |
491 | cr.cxt=0; |
492 | ++cr.limit; |
493 | cr.limit&=(1<<cp[2])-1; |
494 | if(cr.a==0){ |
495 | cr.b=cr.limit-cr.cm(h[i]); |
496 | if(cr.b&(cr.ht.size()-1)) |
497 | while(cr.a<255&&cr.ht(cr.limit-cr.a-1)==cr.ht(cr.limit-cr.a-cr.b-1)) |
498 | ++cr.a; |
499 | } |
500 | else cr.a+=cr.a<255; |
501 | cr.cm(h[i])=cr.limit; |
502 | } |
503 | } |
504 | break; |
505 | case MIX2:{ |
506 | int err=(y*32767-squash(p[i]))*cp[4]>>5; |
507 | int w=cr.a16[cr.cxt]; |
508 | w+=(err*(p[cp[2]]-p[cp[3]])+(1<<12))>>13; |
509 | if(w<0)w=0; |
510 | if(w>65535)w=65535; |
511 | cr.a16[cr.cxt]=w; |
512 | } |
513 | break; |
514 | case MIX:{ |
515 | int m=cp[3]; |
516 | int err=(y*32767-squash(p[i]))*cp[4]>>4; |
517 | int*wt=(int*)&cr.cm[cr.cxt]; |
518 | for(int j=0;j<m;++j) |
519 | wt[j]=clamp512k(wt[j]+((err*p[cp[2]+j]+(1<<12))>>13)); |
520 | } |
521 | break; |
522 | case ISSE:{ |
523 | int err=y*32767-squash(p[i]); |
524 | int*wt=(int*)&cr.cm[cr.cxt*2]; |
525 | wt[0]=clamp512k(wt[0]+((err*p[cp[2]]+(1<<12))>>13)); |
526 | wt[1]=clamp512k(wt[1]+((err+16)>>5)); |
527 | cr.ht[cr.c+(hmap4&15)]=st.ns[cr.cxt*4+y]; |
528 | } |
529 | break; |
530 | case SSE: |
531 | train(cr,y); |
532 | } |
533 | cp+=compsize[cp[0]]; |
534 | } |
535 | c8+=c8+y; |
536 | if(c8>=256){ |
537 | z.run(c8-256); |
538 | hmap4=1; |
539 | c8=1; |
540 | for(int i=0;i<n;++i)h[i]=z.h(i); |
541 | } |
542 | else if(c8>=16&&c8<32) |
543 | hmap4=(hmap4&0xf)<<5|y<<4|1; |
544 | else |
545 | hmap4=(hmap4&0x1f0)|(((hmap4&0xf)*2+y)&0xf); |
546 | } |
547 | size_t PR::find(Array<U8>&ht,int sizebits,U32 cxt){ |
548 | int chk=cxt>>sizebits&255; |
549 | size_t h0=(cxt*16)&(ht.size()-16); |
550 | if(ht[h0]==chk)return h0; |
551 | size_t h1=h0^16; |
552 | if(ht[h1]==chk)return h1; |
553 | size_t h2=h0^32; |
554 | if(ht[h2]==chk)return h2; |
555 | if(ht[h0+1]<=ht[h1+1]&&ht[h0+1]<=ht[h2+1]) |
556 | return memset(&ht[h0],0,16),ht[h0]=chk,h0; |
557 | else if(ht[h1+1]<ht[h2+1]) |
558 | return memset(&ht[h1],0,16),ht[h1]=chk,h1; |
559 | else |
560 | return memset(&ht[h2],0,16),ht[h2]=chk,h2; |
561 | } |
562 | struct DE{ |
563 | FILE*in; |
564 | DE(ZP&z); |
565 | int de(); |
566 | void init(); |
567 | U32 low,high; |
568 | U32 curr; |
569 | PR pr; |
570 | int decode(int p); |
571 | } |
572 | ; |
573 | DE::DE(ZP&z): |
574 | in(0),low(1),high(0xFFFFFFFF),curr(0),pr(z){ |
575 | } |
576 | void DE::init(){ |
577 | pr.init(); |
578 | if(pr.im())low=1,high=0xFFFFFFFF,curr=0; |
579 | else low=high=curr=0; |
580 | } |
581 | int DE::decode(int p){ |
582 | U32 mid=low+U32(((high-low)*U64(U32(p)))>>16); |
583 | int y=curr<=mid; |
584 | if(y)high=mid; |
585 | else low=mid+1; |
586 | while((high^low)<0x1000000){ |
587 | high=high<<8|255; |
588 | low=low<<8; |
589 | low+=(low==0); |
590 | curr=curr<<8|getc(in); |
591 | } |
592 | return y; |
593 | } |
594 | int DE::de(){ |
595 | if(pr.im()){ |
596 | if(curr==0){ |
597 | for(int i=0;i<4;++i) |
598 | curr=curr<<8|getc(in); |
599 | } |
600 | if(decode(0)){ |
601 | return -1; |
602 | } |
603 | else{ |
604 | int c=1; |
605 | while(c<256){ |
606 | int p=pr.predict()*2+1; |
607 | c+=c+decode(p); |
608 | pr.update(c&1); |
609 | } |
610 | return c-256; |
611 | } |
612 | } |
613 | else{ |
614 | if(curr==0){ |
615 | for(int i=0;i<4;++i) |
616 | curr=curr<<8|getc(in); |
617 | if(curr==0)return -1; |
618 | } |
619 | --curr; |
620 | return getc(in); |
621 | } |
622 | } |
623 | struct PP{ |
624 | int state; |
625 | int hsize; |
626 | int ph,pm; |
627 | ZP z; |
628 | PP():state(0),hsize(0),ph(0),pm(0){ |
629 | } |
630 | void init(int h,int m); |
631 | int write(int c); |
632 | } |
633 | ; |
634 | void PP::init(int h,int m){ |
635 | state=hsize=0; |
636 | ph=h; |
637 | pm=m; |
638 | z.clear(); |
639 | } |
640 | int PP::write(int c){ |
641 | switch(state){ |
642 | case 0: |
643 | state=c+1; |
644 | if(state==1)z.clear(); |
645 | break; |
646 | case 1: |
647 | if(c>=0&&z.out)putc(c,z.out); |
648 | break; |
649 | case 2: |
650 | hsize=c; |
651 | state=3; |
652 | break; |
653 | case 3: |
654 | hsize+=c*256; |
655 | z.hd.resize(hsize+300); |
656 | z.cend=8; |
657 | z.hbegin=z.hend=z.cend+128; |
658 | z.hd[4]=ph; |
659 | z.hd[5]=pm; |
660 | state=4; |
661 | break; |
662 | case 4: |
663 | z.hd[z.hend++]=c; |
664 | if(z.hend-z.hbegin==hsize){ |
665 | hsize=z.cend-2+z.hend-z.hbegin; |
666 | z.hd[0]=hsize&255; |
667 | z.hd[1]=hsize>>8; |
668 | z.init(z.hd[4],z.hd[5]); |
669 | state=5; |
670 | } |
671 | break; |
672 | case 5: |
673 | z.run(c); |
674 | break; |
675 | } |
676 | return state; |
677 | } |
678 | struct DC{ |
679 | DC():z(),dec(z),pp(),ds(0){ |
680 | } |
681 | bool fb(); |
682 | bool ff(string&); |
683 | void de(); |
684 | ZP z; |
685 | DE dec; |
686 | PP pp; |
687 | int ds; |
688 | } |
689 | ; |
690 | bool DC::fb(){ |
691 | U32 h1=0x3D49B113,h2=0x29EB7F93,h3=0x2614BE13,h4=0x3828EB13; |
692 | int c; |
693 | while((c=getc(dec.in))!=EOF){ |
694 | h1=h1*12+c; |
695 | h2=h2*20+c; |
696 | h3=h3*28+c; |
697 | h4=h4*44+c; |
698 | if(h1==0xB16B88F1&&h2==0xFF5376F1&&h3==0x72AC5BF1&&h4==0x2F909AF1) |
699 | break; |
700 | } |
701 | if(c<0)return false; |
702 | getc(dec.in); |
703 | getc(dec.in); |
704 | z.read(dec.in); |
705 | ds=0; |
706 | return true; |
707 | } |
708 | bool DC::ff(string&filename){ |
709 | int c=getc(dec.in); |
710 | if(c==1){ |
711 | while(true){ |
712 | c=getc(dec.in); |
713 | if(c==0){ |
714 | return true; |
715 | } |
716 | filename+=char(c); |
717 | } |
718 | } |
719 | return false; |
720 | } |
721 | void DC::de(){ |
722 | while(getc(dec.in)); |
723 | getc(dec.in); |
724 | if(ds==0){ |
725 | dec.init(); |
726 | pp.init(z.hd[4],z.hd[5]); |
727 | ds=1; |
728 | } |
729 | while((pp.state&3)!=1) |
730 | pp.write(dec.de()); |
731 | while(true){ |
732 | int c=dec.de(); |
733 | pp.write(c); |
734 | if(c==-1)break; |
735 | } |
736 | if(getc(dec.in)==253){ |
737 | for(int i=1;i<=20;++i) |
738 | getc(dec.in); |
739 | } |
740 | } |
741 | int main(int argc,char**argv){ |
742 | DC d; |
743 | if(argc<2||!(d.dec.in=fopen(argv[1],"rb")))return 0; |
744 | string sout; |
745 | while(d.fb()){ |
746 | while(d.ff(sout)){ |
747 | if(sout!=""){ |
748 | if(d.pp.z.out)fclose(d.pp.z.out); |
749 | d.pp.z.out=fopen(sout.c_str(),"wb"); |
750 | sout=""; |
751 | } |
752 | d.de(); |
753 | } |
754 | } |
755 | return 0; |
756 | } |
Travelled to 4 computer(s): bhatertpkbcr, mqqgnosmbjvj, pyentgdyhuwx, vouqrxazstgt
No comments. add comment
Snippet ID: | #1031420 |
Snippet name: | ZPAQ decompressor, C++ |
Eternal ID of this version: | #1031420/1 |
Text MD5: | e5d306ed04e90a89961178559ec6be72 |
Author: | stefan |
Category: | zpaq |
Type: | Document |
Public (visible to everyone): | Yes |
Archived (hidden from active list): | No |
Created/modified: | 2021-06-12 04:30:25 |
Source code size: | 13106 bytes / 756 lines |
Pitched / IR pitched: | No / No |
Views / Downloads: | 196 / 213 |
Referenced in: | [show references] |