00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035 #include "CompressMan.hpp"
00036
00037 #ifdef XDEMILL
00038 #include "UnCompCont.hpp"
00039 #endif
00040
00041 struct DivCompressorItem
00042
00043
00044 {
00045 DivCompressorItem *next;
00046 #ifdef XMILL
00047 UserCompressor *usercompressor;
00048 #endif
00049 #ifdef XDEMILL
00050 UserUncompressor *useruncompressor;
00051 #endif
00052
00053
00054
00055
00056 char *afterseparator;
00057 unsigned short afterseparatorlen;
00058
00059 unsigned short curitemlen;
00060
00061
00062
00063 void *operator new(size_t size) { return mainmem.GetByteBlock(size);}
00064 void operator delete(void *ptr) {}
00065 };
00066
00067 struct DivSepComprInfo
00068
00069 {
00070
00071 char *startseparator;
00072 unsigned long startseparatorlen;
00073
00074 DivCompressorItem *subcompressors;
00075
00076 void CreateSubCompressors(char *paramstr,int len)
00077
00078 {
00079 char *endstringptr;
00080 DivCompressorItem **curitemref;
00081
00082 char *ptr=paramstr;
00083 char *endptr=paramstr+len;
00084
00085 if(*ptr=='"')
00086 {
00087 endstringptr=::ParseString(ptr,ptr+len);
00088
00089 startseparator=ptr+1;
00090 startseparatorlen=endstringptr-ptr-1;
00091
00092 ptr=endstringptr+1;
00093 }
00094 else
00095 {
00096 startseparator=NULL;
00097 startseparatorlen=0;
00098 }
00099
00100
00101
00102 curitemref=&subcompressors;
00103 *curitemref=NULL;
00104
00105 do
00106 {
00107 ptr=SkipWhiteSpaces(ptr,endptr);
00108 if(ptr==endptr)
00109 break;
00110
00111
00112
00113 *curitemref=new DivCompressorItem();
00114
00115 #ifdef XMILL
00116 (*curitemref)->usercompressor=compressman.CreateCompressorInstance(ptr,endptr);
00117 #endif
00118 #ifdef XDEMILL
00119 (*curitemref)->useruncompressor=compressman.CreateUncompressorInstance(ptr,endptr);
00120 #endif
00121
00122 (*curitemref)->next=NULL;
00123
00124
00125
00126 ptr=SkipWhiteSpaces(ptr,endptr);
00127 if(ptr==endptr)
00128 break;
00129
00130
00131 endstringptr=::ParseString(ptr,endptr);
00132
00133
00134 (*curitemref)->afterseparator=ptr+1;
00135 (*curitemref)->afterseparatorlen=endstringptr-ptr-1;
00136
00137 ptr=endstringptr+1;
00138
00139 curitemref=&((*curitemref)->next);
00140 *curitemref=NULL;
00141 }
00142 while(1);
00143
00144 if(*curitemref!=NULL)
00145 {
00146 (*curitemref)->afterseparator=NULL;
00147 (*curitemref)->afterseparatorlen=0;
00148 }
00149 }
00150 };
00151
00152
00153
00154
00155
00156 class DivSepCompressorFactory;
00157
00158 #ifdef XMILL
00159
00160 class DivSepCompressor : public UserCompressor
00161 {
00162 friend DivSepCompressorFactory;
00163 protected:
00164
00165 DivSepComprInfo info;
00166
00167 public:
00168 void ComputeProperties()
00169 {
00170 isrejecting=1;canoverlap=1;
00171 isfixedlen=1;
00172 datasize=0;
00173 contnum=0;
00174
00175 DivCompressorItem *item=info.subcompressors;
00176 while(item!=NULL)
00177 {
00178 datasize+=item->usercompressor->GetUserDataSize();
00179 contnum+=item->usercompressor->GetUserContNum();
00180
00181 if(item->usercompressor->CanOverlap()==0)
00182 canoverlap=0;
00183
00184
00185
00186 if(item->usercompressor->IsFixedLen()==0)
00187 isfixedlen=0;
00188
00189 item=item->next;
00190 }
00191 }
00192
00193 void CreateSubCompressors(char *paramstr,int len)
00194 {
00195 info.CreateSubCompressors(paramstr,len);
00196 }
00197
00198 void InitCompress(CompressContainer *cont,char *dataptr)
00199
00200 {
00201 DivCompressorItem *item=info.subcompressors;
00202
00203 while(item!=NULL)
00204 {
00205 item->usercompressor->InitCompress(cont,dataptr);
00206 cont+=item->usercompressor->GetUserContNum();
00207 dataptr+=item->usercompressor->GetUserDataSize();
00208 item=item->next;
00209 }
00210 }
00211
00212 char ParseString(char *str,unsigned len,char *dataptr)
00213 {
00214 char *ptr1=str,
00215 *ptr2,*curptr,*endptr,*itemptr;
00216 DivCompressorItem *item;
00217 unsigned i;
00218
00219
00220 if(info.startseparator!=NULL)
00221 {
00222 ptr1=str;
00223 ptr2=info.startseparator;
00224
00225
00226
00227 if(len<info.startseparatorlen)
00228 return 0;
00229
00230
00231 for(i=0;i<info.startseparatorlen;i++)
00232 {
00233 if(*ptr1!=*ptr2)
00234 return 0;
00235 ptr1++;
00236 ptr2++;
00237 }
00238 itemptr=ptr1;
00239 }
00240 else
00241 itemptr=str;
00242
00243 item=info.subcompressors;
00244
00245
00246
00247
00248 while(item->next!=NULL)
00249 {
00250 curptr=itemptr;
00251 endptr=str+len-item->afterseparatorlen;
00252
00253
00254
00255 while(curptr<endptr)
00256 {
00257 ptr1=curptr;
00258 ptr2=item->afterseparator;
00259
00260 for(i=0;i<item->afterseparatorlen;i++)
00261 {
00262 if(*ptr1!=*ptr2)
00263 break;
00264 ptr1++;
00265 ptr2++;
00266 }
00267
00268 if(i==item->afterseparatorlen)
00269 break;
00270
00271 curptr++;
00272 }
00273
00274 if(curptr>=endptr)
00275
00276 return 0;
00277
00278
00279
00280 item->curitemlen=curptr-itemptr;
00281
00282
00283 if(item->usercompressor->ParseString(itemptr,curptr-itemptr,dataptr)==0)
00284 return 0;
00285
00286 dataptr+=item->usercompressor->GetUserDataSize();
00287
00288 itemptr=ptr1;
00289 item=item->next;
00290 }
00291
00292 endptr=str+len;
00293
00294
00295
00296 if(item->afterseparator!=NULL)
00297 {
00298 ptr1=endptr-item->afterseparatorlen;
00299 if(ptr1<itemptr)
00300 return 0;
00301 ptr2=item->afterseparator;
00302
00303 for(i=0;i<item->afterseparatorlen;i++)
00304 {
00305 if(*ptr1!=*ptr2)
00306 return 0;
00307 ptr1++;
00308 ptr2++;
00309 }
00310 endptr-=item->afterseparatorlen;
00311 }
00312
00313 item->curitemlen=endptr-itemptr;
00314
00315
00316 if(item->usercompressor->ParseString(itemptr,endptr-itemptr,dataptr)==0)
00317 return 0;
00318
00319 return 1;
00320 }
00321
00322 void CompressString(char *str,unsigned len,CompressContainer *cont,char *dataptr)
00323
00324
00325
00326
00327
00328 {
00329 DivCompressorItem *item=info.subcompressors;
00330 char *startitemptr;
00331
00332
00333 startitemptr=str+info.startseparatorlen;
00334
00335 while(item!=NULL)
00336 {
00337
00338
00339 item->usercompressor->CompressString(startitemptr,item->curitemlen,cont,dataptr);
00340
00341 cont+=item->usercompressor->GetUserContNum();
00342 dataptr+=item->usercompressor->GetUserDataSize();
00343
00344
00345 startitemptr+=item->curitemlen+item->afterseparatorlen;
00346 item=item->next;
00347 }
00348 }
00349
00350 void FinishCompress(CompressContainer *cont,char *dataptr)
00351
00352
00353
00354 {
00355 DivCompressorItem *item=info.subcompressors;
00356
00357 while(item!=NULL)
00358 {
00359 item->usercompressor->FinishCompress(cont,dataptr);
00360
00361 cont+=item->usercompressor->GetUserContNum();
00362 dataptr+=item->usercompressor->GetUserDataSize();
00363
00364 item=item->next;
00365 }
00366 }
00367
00368 void PrintCompressInfo(char *dataptr,unsigned long *overalluncomprsize,unsigned long *overallcomprsize)
00369
00370
00371 {
00372 DivCompressorItem *item=info.subcompressors;
00373
00374 while(item!=NULL)
00375 {
00376 item->usercompressor->PrintCompressInfo(dataptr,overalluncomprsize,overallcomprsize);
00377
00378 dataptr+=item->usercompressor->GetUserDataSize();
00379
00380 item=item->next;
00381 }
00382 }
00383 };
00384
00385 #endif // XMILL
00386
00387
00388
00389
00390
00391
00392 #ifdef XDEMILL
00393
00394 class DivSepUncompressor : public UserUncompressor
00395 {
00396 friend DivSepCompressorFactory;
00397 protected:
00398
00399 DivSepComprInfo info;
00400
00401 public:
00402 void ComputeProperties()
00403
00404 {
00405 DivCompressorItem *item=info.subcompressors;
00406
00407 datasize=0;
00408 contnum=0;
00409
00410 while(item!=NULL)
00411 {
00412 datasize+=item->useruncompressor->GetUserDataSize();
00413 contnum+=item->useruncompressor->GetUserContNum();
00414 item=item->next;
00415 }
00416 }
00417
00418 void CreateSubCompressors(char *paramstr,int len)
00419
00420
00421 {
00422 info.CreateSubCompressors(paramstr,len);
00423 }
00424
00425 void InitUncompress(UncompressContainer *cont,char *dataptr)
00426
00427 {
00428 DivCompressorItem *item=info.subcompressors;
00429
00430 while(item!=NULL)
00431 {
00432 item->useruncompressor->InitUncompress(cont,dataptr);
00433 cont+=item->useruncompressor->GetUserContNum();
00434 dataptr+=item->useruncompressor->GetUserDataSize();
00435 item=item->next;
00436 }
00437 }
00438
00439 void UncompressItem(UncompressContainer *cont,char *dataptr,XMLOutput *output)
00440
00441
00442 {
00443 DivCompressorItem *item=info.subcompressors;
00444
00445
00446 if(info.startseparator!=NULL)
00447 output->characters(info.startseparator,info.startseparatorlen);
00448
00449
00450
00451 while(item!=NULL)
00452 {
00453 item->useruncompressor->UncompressItem(cont,dataptr,output);
00454
00455 if(item->afterseparator!=NULL)
00456 output->characters(item->afterseparator,item->afterseparatorlen);
00457
00458 cont+=item->useruncompressor->GetUserContNum();
00459 dataptr+=item->useruncompressor->GetUserDataSize();
00460
00461 item=item->next;
00462 }
00463 }
00464
00465 void FinishUncompress(UncompressContainer *cont,char *dataptr)
00466
00467 {
00468 DivCompressorItem *item=info.subcompressors;
00469
00470 while(item!=NULL)
00471 {
00472 item->useruncompressor->FinishUncompress(cont,dataptr);
00473
00474 cont+=item->useruncompressor->GetUserContNum();
00475 dataptr+=item->useruncompressor->GetUserDataSize();
00476
00477 item=item->next;
00478 }
00479 }
00480 };
00481
00482 #endif
00483
00484
00485
00486 class DivSepCompressorFactory : public UserCompressorFactory
00487
00488 {
00489 public:
00490 char *GetName() { return "seq"; }
00491 char *GetDescription() { return "Sequence compressor for strings with separators"; }
00492
00493 #ifdef XMILL
00494 UserCompressor *InstantiateCompressor(char *paramstr,int len)
00495
00496 {
00497 if(paramstr==NULL)
00498 {
00499 Error("Sequence compressor 'seq' must have a sequence of strings and compressors as parameters");
00500 Exit();
00501 }
00502
00503 DivSepCompressor *divsepcompressor=new DivSepCompressor();
00504
00505
00506 divsepcompressor->CreateSubCompressors(paramstr,len);
00507 divsepcompressor->ComputeProperties();
00508 return divsepcompressor;
00509 }
00510 #endif
00511
00512 #ifdef XDEMILL
00513 UserUncompressor *InstantiateUncompressor(char *paramstr,int len)
00514
00515 {
00516 DivSepUncompressor *divsepuncompressor=new DivSepUncompressor();
00517
00518
00519 divsepuncompressor->CreateSubCompressors(paramstr,len);
00520 divsepuncompressor->ComputeProperties();
00521 return divsepuncompressor;
00522 }
00523 #endif
00524 };
00525
00526
00527 DivSepCompressorFactory divsepcompressfactory;
00528
00529
00530
00531
00532
00533
00534
00535
00536
00537
00538
00539
00540
00541
00542 #ifdef XMILL
00543
00544 class DivCombineCompressor : public DivSepCompressor
00545
00546
00547 {
00548 friend DivSepCompressorFactory;
00549
00550 public:
00551 void ComputeProperties()
00552 {
00553 isrejecting=1;canoverlap=1;
00554 isfixedlen=1;
00555 datasize=0;
00556 contnum=0;
00557
00558 DivCompressorItem *item=info.subcompressors;
00559 while(item!=NULL)
00560 {
00561 datasize+=item->usercompressor->GetUserDataSize();
00562
00563
00564 if(contnum<item->usercompressor->GetUserContNum())
00565 contnum=item->usercompressor->GetUserContNum();
00566
00567 if(item->usercompressor->CanOverlap()==0)
00568 canoverlap=0;
00569
00570 if(item->usercompressor->IsFixedLen()==0)
00571 isfixedlen=0;
00572
00573 item=item->next;
00574 }
00575 }
00576
00577 void CreateSubCompressors(char *paramstr,int len)
00578 {
00579 info.CreateSubCompressors(paramstr,len);
00580 }
00581
00582 void InitCompress(CompressContainer *cont,char *dataptr)
00583 {
00584 DivCompressorItem *item=info.subcompressors;
00585
00586 while(item!=NULL)
00587 {
00588
00589 item->usercompressor->InitCompress(cont,dataptr);
00590 dataptr+=item->usercompressor->GetUserDataSize();
00591 item=item->next;
00592 }
00593 }
00594
00595 void CompressString(char *str,unsigned len,CompressContainer *cont,char *dataptr)
00596
00597
00598
00599
00600
00601 {
00602 DivCompressorItem *item=info.subcompressors;
00603 char *startitemptr;
00604
00605 startitemptr=str+info.startseparatorlen;
00606
00607 while(item!=NULL)
00608 {
00609 item->usercompressor->CompressString(startitemptr,item->curitemlen,cont,dataptr);
00610 dataptr+=item->usercompressor->GetUserDataSize();
00611
00612 startitemptr+=item->curitemlen+item->afterseparatorlen;
00613 item=item->next;
00614 }
00615 }
00616
00617 void FinishCompress(CompressContainer *cont,char *dataptr)
00618
00619
00620 {
00621 DivCompressorItem *item=info.subcompressors;
00622
00623 while(item!=NULL)
00624 {
00625 item->usercompressor->FinishCompress(cont,dataptr);
00626 dataptr+=item->usercompressor->GetUserDataSize();
00627 item=item->next;
00628 }
00629 }
00630
00631 void PrintCompressInfo(char *dataptr,unsigned long *overalluncomprsize,unsigned long *overallcomprsize)
00632
00633
00634 {
00635 DivCompressorItem *item=info.subcompressors;
00636
00637 while(item!=NULL)
00638 {
00639 item->usercompressor->PrintCompressInfo(dataptr,overalluncomprsize,overallcomprsize);
00640
00641 dataptr+=item->usercompressor->GetUserDataSize();
00642
00643 item=item->next;
00644 }
00645 }
00646 };
00647
00648 #endif
00649
00650
00651
00652
00653
00654 #ifdef XDEMILL
00655
00656 class DivCombineUncompressor : public DivSepUncompressor
00657
00658
00659 {
00660 friend DivSepCompressorFactory;
00661
00662 public:
00663 void ComputeProperties()
00664
00665
00666
00667 {
00668 DivCompressorItem *item=info.subcompressors;
00669
00670 datasize=0;
00671 contnum=0;
00672
00673 while(item!=NULL)
00674 {
00675 datasize+=item->useruncompressor->GetUserDataSize();
00676
00677
00678 if(contnum<item->useruncompressor->GetUserContNum())
00679 contnum=item->useruncompressor->GetUserContNum();
00680 item=item->next;
00681 }
00682 }
00683
00684 void CreateSubCompressors(char *paramstr,int len)
00685 {
00686 info.CreateSubCompressors(paramstr,len);
00687 }
00688
00689 void InitUncompress(UncompressContainer *cont,char *dataptr)
00690
00691 {
00692 DivCompressorItem *item=info.subcompressors;
00693
00694 while(item!=NULL)
00695 {
00696 item->useruncompressor->InitUncompress(cont,dataptr);
00697
00698 dataptr+=item->useruncompressor->GetUserDataSize();
00699 item=item->next;
00700 }
00701 }
00702
00703 void UncompressItem(UncompressContainer *cont,char *dataptr,XMLOutput *output)
00704
00705
00706 {
00707 DivCompressorItem *item=info.subcompressors;
00708
00709 if(info.startseparator!=NULL)
00710 output->characters(info.startseparator,info.startseparatorlen);
00711
00712 while(item!=NULL)
00713 {
00714 item->useruncompressor->UncompressItem(cont,dataptr,output);
00715 if(item->afterseparator!=NULL)
00716 output->characters(item->afterseparator,item->afterseparatorlen);
00717 dataptr+=item->useruncompressor->GetUserDataSize();
00718
00719 item=item->next;
00720 }
00721 }
00722
00723 void FinishUncompress(UncompressContainer *cont,char *dataptr)
00724
00725 {
00726 DivCompressorItem *item=info.subcompressors;
00727
00728 while(item!=NULL)
00729 {
00730 item->useruncompressor->FinishUncompress(cont,dataptr);
00731 dataptr+=item->useruncompressor->GetUserDataSize();
00732 item=item->next;
00733 }
00734 }
00735 };
00736
00737 #endif
00738
00739
00740
00741 class DivCombineCompressorFactory : public DivSepCompressorFactory
00742
00743 {
00744 public:
00745 char *GetName() { return "seqcomb"; }
00746 char *GetDescription() { return "Combined sequence compressor for strings with separators"; }
00747
00748 #ifdef XMILL
00749 UserCompressor *InstantiateCompressor(char *paramstr,int len)
00750 {
00751 if(paramstr==NULL)
00752 {
00753 Error("Combined sequence compressor 'seqcomb' must have a sequence of strings and compressors as parameters");
00754 Exit();
00755 }
00756
00757 DivCombineCompressor *divcombcompressor=new DivCombineCompressor();
00758
00759
00760 divcombcompressor->CreateSubCompressors(paramstr,len);
00761 divcombcompressor->ComputeProperties();
00762 return divcombcompressor;
00763 }
00764 #endif
00765
00766 #ifdef XDEMILL
00767 UserUncompressor *InstantiateUncompressor(char *paramstr,int len)
00768 {
00769 DivCombineUncompressor *divcombuncompressor=new DivCombineUncompressor();
00770
00771
00772 divcombuncompressor->CreateSubCompressors(paramstr,len);
00773 divcombuncompressor->ComputeProperties();
00774 return divcombuncompressor;
00775 }
00776 #endif
00777 };
00778
00779
00780 DivCombineCompressorFactory divcombcompressfactory;