13b7203622 2011-02-23 kinaba: 13b7203622 2011-02-23 kinaba: #include "stdafx.h" 13b7203622 2011-02-23 kinaba: #include "ArcMsc.h" 13b7203622 2011-02-23 kinaba: #include "NoahApp.h" 13b7203622 2011-02-23 kinaba: 13b7203622 2011-02-23 kinaba: bool CArcMsc::header( kiFile& fp, unsigned long* siz, char* ext ) 13b7203622 2011-02-23 kinaba: { 13b7203622 2011-02-23 kinaba: // 読み出す 13b7203622 2011-02-23 kinaba: unsigned char p[14]; 13b7203622 2011-02-23 kinaba: if( 14!=fp.read(p,14) ) 13b7203622 2011-02-23 kinaba: return false; 13b7203622 2011-02-23 kinaba: 13b7203622 2011-02-23 kinaba: // ヘッダ構造:SZDD芋'3A [ext3rd] [orisiz(dword)] 13b7203622 2011-02-23 kinaba: static const unsigned char head[9]={ 0x53,0x5A,0x44,0x44,0x88,0xF0,0x27,0x33,0x41 };//="SZDD芋'3A"; 13b7203622 2011-02-23 kinaba: 13b7203622 2011-02-23 kinaba: for( int i=0; i!=9; i++ ) 13b7203622 2011-02-23 kinaba: if( p[i]!=head[i] ) 13b7203622 2011-02-23 kinaba: return false; 13b7203622 2011-02-23 kinaba: 13b7203622 2011-02-23 kinaba: if( ext ) 13b7203622 2011-02-23 kinaba: *ext = (char)p[9]; 13b7203622 2011-02-23 kinaba: 13b7203622 2011-02-23 kinaba: DWORD x = p[10]+(p[11]<<8)+(p[12]<<16)+(p[13]<<24); 13b7203622 2011-02-23 kinaba: if( siz ) 13b7203622 2011-02-23 kinaba: *siz=x; 13b7203622 2011-02-23 kinaba: 13b7203622 2011-02-23 kinaba: // 原理的に、16倍という圧縮率は出ない 13b7203622 2011-02-23 kinaba: return (x <= fp.getSize()*16); 13b7203622 2011-02-23 kinaba: } 13b7203622 2011-02-23 kinaba: 13b7203622 2011-02-23 kinaba: void CArcMsc::filename( char* oname, const char* ol, char ext ) 13b7203622 2011-02-23 kinaba: { 13b7203622 2011-02-23 kinaba: // コピー 13b7203622 2011-02-23 kinaba: ki_strcpy( oname, ol ); 13b7203622 2011-02-23 kinaba: 13b7203622 2011-02-23 kinaba: // 最後が '_' なら消しておく。 13b7203622 2011-02-23 kinaba: bool bIs_=false; 13b7203622 2011-02-23 kinaba: for( char* p=oname; *p; p=kiStr::next(p) ) 13b7203622 2011-02-23 kinaba: bIs_ = (*p=='_'); 13b7203622 2011-02-23 kinaba: if( bIs_ ) 13b7203622 2011-02-23 kinaba: *(--p)='\0'; 13b7203622 2011-02-23 kinaba: 13b7203622 2011-02-23 kinaba: 13b7203622 2011-02-23 kinaba: if( ext ) 13b7203622 2011-02-23 kinaba: { 13b7203622 2011-02-23 kinaba: // 拡張子復元 13b7203622 2011-02-23 kinaba: *p++ = ext; 13b7203622 2011-02-23 kinaba: *p = '\0'; 13b7203622 2011-02-23 kinaba: } 13b7203622 2011-02-23 kinaba: else 13b7203622 2011-02-23 kinaba: { 13b7203622 2011-02-23 kinaba: // 拡張子自動補完 13b7203622 2011-02-23 kinaba: const char* x = kiPath::ext(oname); 13b7203622 2011-02-23 kinaba: if( ki_strlen(x)==2 ) 13b7203622 2011-02-23 kinaba: { 13b7203622 2011-02-23 kinaba: ::CharLower(oname); 13b7203622 2011-02-23 kinaba: 13b7203622 2011-02-23 kinaba: if( 0==ki_strcmp(x,"ex") )(*p++)='e'; 13b7203622 2011-02-23 kinaba: else if( 0==ki_strcmp(x,"co") )(*p++)='m'; 13b7203622 2011-02-23 kinaba: else if( 0==ki_strcmp(x,"sc") )(*p++)='r'; 13b7203622 2011-02-23 kinaba: 13b7203622 2011-02-23 kinaba: else if( 0==ki_strcmp(x,"dl") )(*p++)='l'; 13b7203622 2011-02-23 kinaba: else if( 0==ki_strcmp(x,"oc") )(*p++)='x'; 13b7203622 2011-02-23 kinaba: else if( 0==ki_strcmp(x,"dr") )(*p++)='v'; 13b7203622 2011-02-23 kinaba: else if( 0==ki_strcmp(x,"vx") )(*p++)='d'; 13b7203622 2011-02-23 kinaba: else if( 0==ki_strcmp(x,"38") )(*p++)='6'; 13b7203622 2011-02-23 kinaba: else if( 0==ki_strcmp(x,"sy") )(*p++)='s'; 13b7203622 2011-02-23 kinaba: else if( 0==ki_strcmp(x,"cp") )(*p++)='l'; 13b7203622 2011-02-23 kinaba: else if( 0==ki_strcmp(x,"li") )(*p++)='b'; 13b7203622 2011-02-23 kinaba: else if( 0==ki_strcmp(x,"tt") )(*p++)='f'; 13b7203622 2011-02-23 kinaba: 13b7203622 2011-02-23 kinaba: else if( 0==ki_strcmp(x,"ch") )(*p++)='m'; 13b7203622 2011-02-23 kinaba: else if( 0==ki_strcmp(x,"hl") )(*p++)='p'; 13b7203622 2011-02-23 kinaba: else if( 0==ki_strcmp(x,"cn") )(*p++)='t'; 13b7203622 2011-02-23 kinaba: else if( 0==ki_strcmp(x,"da") )(*p++)='t'; 13b7203622 2011-02-23 kinaba: 13b7203622 2011-02-23 kinaba: else if( 0==ki_strcmp(x,"tx") )(*p++)='t'; 13b7203622 2011-02-23 kinaba: else if( 0==ki_strcmp(x,"wr") )(*p++)='i'; 13b7203622 2011-02-23 kinaba: else if( 0==ki_strcmp(x,"wa") )(*p++)='v'; 13b7203622 2011-02-23 kinaba: else if( 0==ki_strcmp(x,"mi") )(*p++)='d'; 13b7203622 2011-02-23 kinaba: else if( 0==ki_strcmp(x,"rm") )(*p++)='i'; 13b7203622 2011-02-23 kinaba: else if( 0==ki_strcmp(x,"bm") )(*p++)='p'; 13b7203622 2011-02-23 kinaba: else if( 0==ki_strcmp(x,"rl") )(*p++)='e'; 13b7203622 2011-02-23 kinaba: else if( 0==ki_strcmp(x,"cu") )(*p++)='r'; 13b7203622 2011-02-23 kinaba: else if( 0==ki_strcmp(x,"do") )(*p++)='c'; 13b7203622 2011-02-23 kinaba: else if( 0==ki_strcmp(x,"ic") )(*p++)='o'; 13b7203622 2011-02-23 kinaba: else if( 0==ki_strcmp(x,"re") )(*p++)='g'; 13b7203622 2011-02-23 kinaba: else if( 0==ki_strcmp(x,"rt") )(*p++)='f'; 13b7203622 2011-02-23 kinaba: else if( 0==ki_strcmp(x,"ht") )(*p++)='m'; 13b7203622 2011-02-23 kinaba: else (*p++)='#'; 13b7203622 2011-02-23 kinaba: 13b7203622 2011-02-23 kinaba: *p = '\0'; 13b7203622 2011-02-23 kinaba: } 13b7203622 2011-02-23 kinaba: } 13b7203622 2011-02-23 kinaba: } 13b7203622 2011-02-23 kinaba: 13b7203622 2011-02-23 kinaba: bool CArcMsc::v_check( const kiPath& aname ) 13b7203622 2011-02-23 kinaba: { 13b7203622 2011-02-23 kinaba: kiFile fp; 13b7203622 2011-02-23 kinaba: if( fp.open( aname ) ) 13b7203622 2011-02-23 kinaba: return header( fp,NULL,NULL ); 13b7203622 2011-02-23 kinaba: return false; 13b7203622 2011-02-23 kinaba: } 13b7203622 2011-02-23 kinaba: 13b7203622 2011-02-23 kinaba: bool CArcMsc::v_list( const arcname& aname, aflArray& files ) 13b7203622 2011-02-23 kinaba: { 13b7203622 2011-02-23 kinaba: kiPath fname(aname.basedir); fname+=aname.lname; 13b7203622 2011-02-23 kinaba: 13b7203622 2011-02-23 kinaba: arcfile x; 13b7203622 2011-02-23 kinaba: kiFile fp; 13b7203622 2011-02-23 kinaba: char ext; 13b7203622 2011-02-23 kinaba: if( !fp.open( fname ) || !header( fp, &x.inf.dwOriginalSize, &ext ) ) 13b7203622 2011-02-23 kinaba: return false; 13b7203622 2011-02-23 kinaba: ki_strcpy( x.inf.szMode, "-msc-" ); 13b7203622 2011-02-23 kinaba: filename( x.inf.szFileName, aname.lname, ext ); 13b7203622 2011-02-23 kinaba: x.inf.dwCompressedSize = fp.getSize(); 13b7203622 2011-02-23 kinaba: x.isfile = true; 13b7203622 2011-02-23 kinaba: 13b7203622 2011-02-23 kinaba: // TODO: 日時をどうする? 13b7203622 2011-02-23 kinaba: 13b7203622 2011-02-23 kinaba: files.add( x ); 13b7203622 2011-02-23 kinaba: return true; 13b7203622 2011-02-23 kinaba: } 13b7203622 2011-02-23 kinaba: 13b7203622 2011-02-23 kinaba: int CArcMsc::v_melt( const arcname& aname, const kiPath& ddir, const aflArray* files ) 13b7203622 2011-02-23 kinaba: { 13b7203622 2011-02-23 kinaba: kiFile fp; 13b7203622 2011-02-23 kinaba: kiPath fname(aname.basedir); fname+=aname.lname; 13b7203622 2011-02-23 kinaba: kiPath oname(ddir); 13b7203622 2011-02-23 kinaba: char tmp[MAX_PATH]; 13b7203622 2011-02-23 kinaba: 13b7203622 2011-02-23 kinaba: // ヘッダ読み込み 13b7203622 2011-02-23 kinaba: char ext; 13b7203622 2011-02-23 kinaba: unsigned long alllen; 13b7203622 2011-02-23 kinaba: if( !fp.open( fname ) || !header(fp,&alllen,&ext) ) 13b7203622 2011-02-23 kinaba: return 0xffff; 13b7203622 2011-02-23 kinaba: fp.close(); 13b7203622 2011-02-23 kinaba: filename( tmp, aname.lname, ext ); 13b7203622 2011-02-23 kinaba: oname += tmp; 13b7203622 2011-02-23 kinaba: 13b7203622 2011-02-23 kinaba: // 書庫・出力先を開く 13b7203622 2011-02-23 kinaba: OFSTRUCT of; 13b7203622 2011-02-23 kinaba: of.cBytes = sizeof(of); 13b7203622 2011-02-23 kinaba: int FROM = ::LZOpenFile( const_cast<char*>((const char*)fname),&of,OF_READ ); 13b7203622 2011-02-23 kinaba: int TO = ::LZOpenFile( const_cast<char*>((const char*)oname),&of,OF_WRITE|OF_CREATE ); 13b7203622 2011-02-23 kinaba: if( FROM<0 || TO<0 ) 13b7203622 2011-02-23 kinaba: return 0xffff; 13b7203622 2011-02-23 kinaba: // 解凍 13b7203622 2011-02-23 kinaba: bool ans = (0<=::LZCopy( FROM,TO )); 13b7203622 2011-02-23 kinaba: // 終了 13b7203622 2011-02-23 kinaba: ::LZClose( TO ); 13b7203622 2011-02-23 kinaba: ::LZClose( FROM ); 13b7203622 2011-02-23 kinaba: return ans?0:0xffff; 13b7203622 2011-02-23 kinaba: } 13b7203622 2011-02-23 kinaba: 13b7203622 2011-02-23 kinaba: int CArcMsc::v_compress( const kiPath& base, const wfdArray& files, const kiPath& ddir, int method, bool sfx ) 13b7203622 2011-02-23 kinaba: { 13b7203622 2011-02-23 kinaba: ::SetCurrentDirectory( base ); 13b7203622 2011-02-23 kinaba: 13b7203622 2011-02-23 kinaba: // 元ファイルを開く 13b7203622 2011-02-23 kinaba: kiFile in; 13b7203622 2011-02-23 kinaba: if( !in.open( files[0].cFileName ) ) 13b7203622 2011-02-23 kinaba: return 0xffff; 13b7203622 2011-02-23 kinaba: 13b7203622 2011-02-23 kinaba: // ヘッダ情報・圧縮先ファイル名 13b7203622 2011-02-23 kinaba: char h_Ext3 = '\0'; 13b7203622 2011-02-23 kinaba: unsigned long h_Len = in.getSize(); 13b7203622 2011-02-23 kinaba: 13b7203622 2011-02-23 kinaba: char aname[MAX_PATH]; 13b7203622 2011-02-23 kinaba: ki_strcpy( aname, files[0].cFileName ); 13b7203622 2011-02-23 kinaba: for( char *x=aname, *last=aname; *x; x=kiStr::next(x) ) 13b7203622 2011-02-23 kinaba: last = x; 13b7203622 2011-02-23 kinaba: if( !IsDBCSLeadByte(*last) ) 13b7203622 2011-02-23 kinaba: h_Ext3=*last; 13b7203622 2011-02-23 kinaba: *last = '_', *(last+1) = '\0'; 13b7203622 2011-02-23 kinaba: 13b7203622 2011-02-23 kinaba: // 圧縮先開く 13b7203622 2011-02-23 kinaba: ::SetCurrentDirectory( ddir ); 13b7203622 2011-02-23 kinaba: 13b7203622 2011-02-23 kinaba: // 圧縮先を開く 13b7203622 2011-02-23 kinaba: kiFile out; 13b7203622 2011-02-23 kinaba: if( !out.open( aname, false ) ) 13b7203622 2011-02-23 kinaba: return 0xffff; 13b7203622 2011-02-23 kinaba: 13b7203622 2011-02-23 kinaba: // タイムスタンプコピー 13b7203622 2011-02-23 kinaba: FILETIME ct, at, mt; 13b7203622 2011-02-23 kinaba: ::GetFileTime(in.getHandle(), &ct, &at, &mt); 13b7203622 2011-02-23 kinaba: ::SetFileTime(out.getHandle(), &ct, &at, &mt); 13b7203622 2011-02-23 kinaba: 13b7203622 2011-02-23 kinaba: // ヘッダ書き込み 13b7203622 2011-02-23 kinaba: unsigned char head[14]={ 0x53,0x5A,0x44,0x44,0x88,0xF0,0x27,0x33,0x41,(unsigned char)h_Ext3, 13b7203622 2011-02-23 kinaba: (unsigned char)(h_Len&0xff),(unsigned char)((h_Len>>8)&0xff), 13b7203622 2011-02-23 kinaba: (unsigned char)((h_Len>>16)&0xff),(unsigned char)((h_Len>>24)&0xff) }; 13b7203622 2011-02-23 kinaba: out.write( head, 14 ); 13b7203622 2011-02-23 kinaba: 13b7203622 2011-02-23 kinaba: // 圧縮作業 13b7203622 2011-02-23 kinaba: CArcProgressDlg dlg( h_Len, true ); 13b7203622 2011-02-23 kinaba: dlg.change( files[0].cFileName ); 13b7203622 2011-02-23 kinaba: if( !do_lzss( in, out, dlg ) ) 13b7203622 2011-02-23 kinaba: { 13b7203622 2011-02-23 kinaba: out.close(); 13b7203622 2011-02-23 kinaba: ::DeleteFile(aname); 13b7203622 2011-02-23 kinaba: return 0x8020; 13b7203622 2011-02-23 kinaba: } 13b7203622 2011-02-23 kinaba: return 0; 13b7203622 2011-02-23 kinaba: } 13b7203622 2011-02-23 kinaba: 13b7203622 2011-02-23 kinaba: 13b7203622 2011-02-23 kinaba: //-- 12bit LZSS -----------------------------------------------// 13b7203622 2011-02-23 kinaba: 13b7203622 2011-02-23 kinaba: 13b7203622 2011-02-23 kinaba: #define N 4096 // slide窓のサイズ 2^12 bytes 13b7203622 2011-02-23 kinaba: #define F 18 // 最長一致長 2^(16-12)+2 bytes 13b7203622 2011-02-23 kinaba: 13b7203622 2011-02-23 kinaba: static unsigned char window[N+F-1]; 13b7203622 2011-02-23 kinaba: static int dad[N+1], lson[N+1], rson[N+257]; 13b7203622 2011-02-23 kinaba: static int matchpos, matchlen; 13b7203622 2011-02-23 kinaba: 13b7203622 2011-02-23 kinaba: static void init_tree() 13b7203622 2011-02-23 kinaba: { 13b7203622 2011-02-23 kinaba: //-- 木を初期化 13b7203622 2011-02-23 kinaba: 13b7203622 2011-02-23 kinaba: int i; 13b7203622 2011-02-23 kinaba: for( i=N+1; i<=N+256; i++ ) // root: 0x00 -- 0xff 13b7203622 2011-02-23 kinaba: rson[i] = N; 13b7203622 2011-02-23 kinaba: for( i=0; i<N ; i++ ) 13b7203622 2011-02-23 kinaba: dad[i] = N; 13b7203622 2011-02-23 kinaba: } 13b7203622 2011-02-23 kinaba: 13b7203622 2011-02-23 kinaba: static void insert_node( int r ) 13b7203622 2011-02-23 kinaba: { 13b7203622 2011-02-23 kinaba: //-- [位置r]から始まる[列str]を木に登録 13b7203622 2011-02-23 kinaba: unsigned char* str = window + r; 13b7203622 2011-02-23 kinaba: rson[r] = lson[r] = N; 13b7203622 2011-02-23 kinaba: 13b7203622 2011-02-23 kinaba: //-- ついでに一致長・位置も記録する 13b7203622 2011-02-23 kinaba: matchlen = 2; 13b7203622 2011-02-23 kinaba: 13b7203622 2011-02-23 kinaba: // 一文字目でrootを選ぶ 13b7203622 2011-02-23 kinaba: int i, p = N+1+str[0], cmp=1; 13b7203622 2011-02-23 kinaba: for(; ;) 13b7203622 2011-02-23 kinaba: { 13b7203622 2011-02-23 kinaba: if( cmp >= 0 ) 13b7203622 2011-02-23 kinaba: { 13b7203622 2011-02-23 kinaba: // 右に進む 13b7203622 2011-02-23 kinaba: if( rson[p] != N ) 13b7203622 2011-02-23 kinaba: p = rson[p]; 13b7203622 2011-02-23 kinaba: // 右にはもうnodeがないのでそこに登録して終了 13b7203622 2011-02-23 kinaba: else 13b7203622 2011-02-23 kinaba: { 13b7203622 2011-02-23 kinaba: rson[p] = r; 13b7203622 2011-02-23 kinaba: dad[r] = p; 13b7203622 2011-02-23 kinaba: return; 13b7203622 2011-02-23 kinaba: } 13b7203622 2011-02-23 kinaba: } 13b7203622 2011-02-23 kinaba: else 13b7203622 2011-02-23 kinaba: { 13b7203622 2011-02-23 kinaba: // 左に進む 13b7203622 2011-02-23 kinaba: if( lson[p] != N ) 13b7203622 2011-02-23 kinaba: p = lson[p]; 13b7203622 2011-02-23 kinaba: // 左にはもうnodeがないのでそこに登録して終了 13b7203622 2011-02-23 kinaba: else 13b7203622 2011-02-23 kinaba: { 13b7203622 2011-02-23 kinaba: lson[p] = r; 13b7203622 2011-02-23 kinaba: dad[r] = p; 13b7203622 2011-02-23 kinaba: return; 13b7203622 2011-02-23 kinaba: } 13b7203622 2011-02-23 kinaba: } 13b7203622 2011-02-23 kinaba: 13b7203622 2011-02-23 kinaba: // 現在のnodeとstrを比較( i==一致長 ) 13b7203622 2011-02-23 kinaba: for( i=1; i<F; i++ ) 13b7203622 2011-02-23 kinaba: if( cmp = str[i] - window[p+i] ) 13b7203622 2011-02-23 kinaba: break; 13b7203622 2011-02-23 kinaba: 13b7203622 2011-02-23 kinaba: // 今まで見つけたものの中で最長だったら記憶 13b7203622 2011-02-23 kinaba: if( i > matchlen ) 13b7203622 2011-02-23 kinaba: { 13b7203622 2011-02-23 kinaba: matchpos = p; 13b7203622 2011-02-23 kinaba: if( (matchlen=i) == F ) 13b7203622 2011-02-23 kinaba: break; 13b7203622 2011-02-23 kinaba: } 13b7203622 2011-02-23 kinaba: } 13b7203622 2011-02-23 kinaba: 13b7203622 2011-02-23 kinaba: // [位置p]の列と長さFで一致した場合、ここに来る 13b7203622 2011-02-23 kinaba: // p の在ったところを r で置き換える 13b7203622 2011-02-23 kinaba: 13b7203622 2011-02-23 kinaba: dad[r] = dad[p]; 13b7203622 2011-02-23 kinaba: lson[r] = lson[p]; 13b7203622 2011-02-23 kinaba: rson[r] = rson[p]; 13b7203622 2011-02-23 kinaba: dad[lson[p]] = r; 13b7203622 2011-02-23 kinaba: dad[rson[p]] = r; 13b7203622 2011-02-23 kinaba: 13b7203622 2011-02-23 kinaba: if( rson[dad[p]]==p ) 13b7203622 2011-02-23 kinaba: rson[dad[p]] = r; 13b7203622 2011-02-23 kinaba: else 13b7203622 2011-02-23 kinaba: lson[dad[p]] = r; 13b7203622 2011-02-23 kinaba: 13b7203622 2011-02-23 kinaba: dad[p] = N; 13b7203622 2011-02-23 kinaba: } 13b7203622 2011-02-23 kinaba: 13b7203622 2011-02-23 kinaba: static void delete_node( int p ) 13b7203622 2011-02-23 kinaba: { 13b7203622 2011-02-23 kinaba: //-- [位置p]の要素を木から削除 13b7203622 2011-02-23 kinaba: 13b7203622 2011-02-23 kinaba: if( dad[p] == N ) // 既に木に入ってないのでおしまい 13b7203622 2011-02-23 kinaba: return; 13b7203622 2011-02-23 kinaba: 13b7203622 2011-02-23 kinaba: int q; 13b7203622 2011-02-23 kinaba: 13b7203622 2011-02-23 kinaba: if( rson[p] == N ) 13b7203622 2011-02-23 kinaba: q = lson[p]; // 唯一の子を上に持ち上げる 13b7203622 2011-02-23 kinaba: else if( lson[p] == N ) 13b7203622 2011-02-23 kinaba: q = rson[p]; // 唯一の子を上に持ち上げる 13b7203622 2011-02-23 kinaba: else 13b7203622 2011-02-23 kinaba: { 13b7203622 2011-02-23 kinaba: q = lson[p]; 13b7203622 2011-02-23 kinaba: 13b7203622 2011-02-23 kinaba: if( rson[q] != N ) 13b7203622 2011-02-23 kinaba: { 13b7203622 2011-02-23 kinaba: // 左の枝の最右、つまり自分より一つ小さいnodeを持ち上げる 13b7203622 2011-02-23 kinaba: do 13b7203622 2011-02-23 kinaba: q = rson[q]; 13b7203622 2011-02-23 kinaba: while( rson[q] != N ); 13b7203622 2011-02-23 kinaba: 13b7203622 2011-02-23 kinaba: rson[dad[q]] = lson[q]; 13b7203622 2011-02-23 kinaba: dad[lson[q]] = dad[q]; 13b7203622 2011-02-23 kinaba: lson[q] = lson[p]; 13b7203622 2011-02-23 kinaba: dad[lson[p]] = q; 13b7203622 2011-02-23 kinaba: } 13b7203622 2011-02-23 kinaba: rson[q] = rson[p]; 13b7203622 2011-02-23 kinaba: dad[rson[p]] = q; 13b7203622 2011-02-23 kinaba: } 13b7203622 2011-02-23 kinaba: 13b7203622 2011-02-23 kinaba: dad[q] = dad[p]; 13b7203622 2011-02-23 kinaba: if( rson[dad[p]] == p ) 13b7203622 2011-02-23 kinaba: rson[dad[p]] = q; 13b7203622 2011-02-23 kinaba: else 13b7203622 2011-02-23 kinaba: lson[dad[p]] = q; 13b7203622 2011-02-23 kinaba: dad[p] = N; 13b7203622 2011-02-23 kinaba: } 13b7203622 2011-02-23 kinaba: 13b7203622 2011-02-23 kinaba: bool CArcMsc::do_lzss( kiFile& in, kiFile& out, CArcProgressDlg& dlg ) 13b7203622 2011-02-23 kinaba: { 13b7203622 2011-02-23 kinaba: int i, c, len, r, s; 13b7203622 2011-02-23 kinaba: unsigned char code[17]={0}, mask=1, codeptr=1; 13b7203622 2011-02-23 kinaba: 13b7203622 2011-02-23 kinaba: s = 2; // s = データ読込位置 13b7203622 2011-02-23 kinaba: r = N - 16; // r = 木への挿入位置 13b7203622 2011-02-23 kinaba: 13b7203622 2011-02-23 kinaba: // クリア 13b7203622 2011-02-23 kinaba: init_tree(); 13b7203622 2011-02-23 kinaba: ki_memset( window+2, ' ', N-F ); 13b7203622 2011-02-23 kinaba: 13b7203622 2011-02-23 kinaba: // 先頭18bytes入力 13b7203622 2011-02-23 kinaba: for( len=0 ; len<F ; len++ ) 13b7203622 2011-02-23 kinaba: { 13b7203622 2011-02-23 kinaba: if( -1 == (c = in.getc()) ) 13b7203622 2011-02-23 kinaba: break; 13b7203622 2011-02-23 kinaba: window[r+len] = c; 13b7203622 2011-02-23 kinaba: } 13b7203622 2011-02-23 kinaba: window[0] = window[r+16]; 13b7203622 2011-02-23 kinaba: window[1] = window[r+17]; 13b7203622 2011-02-23 kinaba: if( len==0 ) 13b7203622 2011-02-23 kinaba: return true; 13b7203622 2011-02-23 kinaba: 13b7203622 2011-02-23 kinaba: // 木へ挿入 13b7203622 2011-02-23 kinaba: for( i=F ; i>=0 ; i-- ) 13b7203622 2011-02-23 kinaba: insert_node( r-i ); 13b7203622 2011-02-23 kinaba: 13b7203622 2011-02-23 kinaba: // ループ 13b7203622 2011-02-23 kinaba: unsigned int total_read=18,prgr_read=0; 13b7203622 2011-02-23 kinaba: 13b7203622 2011-02-23 kinaba: do 13b7203622 2011-02-23 kinaba: { 13b7203622 2011-02-23 kinaba: if( prgr_read > 5000 ) 13b7203622 2011-02-23 kinaba: { 13b7203622 2011-02-23 kinaba: dlg.change( NULL, total_read+=prgr_read ); 13b7203622 2011-02-23 kinaba: prgr_read-=5000; 13b7203622 2011-02-23 kinaba: if( !dlg.msgloop() ) 13b7203622 2011-02-23 kinaba: { 13b7203622 2011-02-23 kinaba: prgr_read=0xffffffff; 13b7203622 2011-02-23 kinaba: break; 13b7203622 2011-02-23 kinaba: } 13b7203622 2011-02-23 kinaba: } 13b7203622 2011-02-23 kinaba: 13b7203622 2011-02-23 kinaba: if( matchlen > len ) 13b7203622 2011-02-23 kinaba: matchlen=len; 13b7203622 2011-02-23 kinaba: 13b7203622 2011-02-23 kinaba: if( matchlen < 3 ) // 一致なし 13b7203622 2011-02-23 kinaba: { 13b7203622 2011-02-23 kinaba: matchlen = 1; 13b7203622 2011-02-23 kinaba: code[0] |= mask; 13b7203622 2011-02-23 kinaba: code[codeptr++] = window[r]; 13b7203622 2011-02-23 kinaba: } 13b7203622 2011-02-23 kinaba: else // 一致あり 13b7203622 2011-02-23 kinaba: { 13b7203622 2011-02-23 kinaba: // [pos&0xff] [pos&0xf00 | len-3] 13b7203622 2011-02-23 kinaba: code[codeptr++] = (unsigned char)matchpos; 13b7203622 2011-02-23 kinaba: code[codeptr++] = (unsigned char)(((matchpos>>4)&0xf0) | (matchlen-3)); 13b7203622 2011-02-23 kinaba: } 13b7203622 2011-02-23 kinaba: 13b7203622 2011-02-23 kinaba: if( (mask<<=1)==0 ) // code が 8Block になっていたら出力 13b7203622 2011-02-23 kinaba: { 13b7203622 2011-02-23 kinaba: out.write( code, codeptr ); 13b7203622 2011-02-23 kinaba: // コードバッファ初期化 13b7203622 2011-02-23 kinaba: code[0] = 0; 13b7203622 2011-02-23 kinaba: codeptr = mask = 1; 13b7203622 2011-02-23 kinaba: } 13b7203622 2011-02-23 kinaba: 13b7203622 2011-02-23 kinaba: // 出力した分読み込む 13b7203622 2011-02-23 kinaba: int lastmatchlen = matchlen; 13b7203622 2011-02-23 kinaba: for( i=0 ; i<lastmatchlen; i++ ) 13b7203622 2011-02-23 kinaba: { 13b7203622 2011-02-23 kinaba: if( -1 == (c=in.getc()) ) 13b7203622 2011-02-23 kinaba: break; 13b7203622 2011-02-23 kinaba: prgr_read++; 13b7203622 2011-02-23 kinaba: 13b7203622 2011-02-23 kinaba: // [位置s]に一文字書き込み 13b7203622 2011-02-23 kinaba: delete_node( s ); 13b7203622 2011-02-23 kinaba: window[s] = c; 13b7203622 2011-02-23 kinaba: if( s < F-1 ) window[ N+s ] = c; 13b7203622 2011-02-23 kinaba: 13b7203622 2011-02-23 kinaba: s = (s+1) & (N-1); // s++ 13b7203622 2011-02-23 kinaba: r = (r+1) & (N-1); // r++ 13b7203622 2011-02-23 kinaba: 13b7203622 2011-02-23 kinaba: // 木に[位置r]のデータを挿入 13b7203622 2011-02-23 kinaba: insert_node( r ); 13b7203622 2011-02-23 kinaba: } 13b7203622 2011-02-23 kinaba: 13b7203622 2011-02-23 kinaba: // EOF後処理 13b7203622 2011-02-23 kinaba: while( i++ < lastmatchlen ) 13b7203622 2011-02-23 kinaba: { 13b7203622 2011-02-23 kinaba: delete_node( s ); 13b7203622 2011-02-23 kinaba: s = (s+1) & (N-1); // s++ 13b7203622 2011-02-23 kinaba: r = (r+1) & (N-1); // r++ 13b7203622 2011-02-23 kinaba: if( --len ) 13b7203622 2011-02-23 kinaba: insert_node( r ); 13b7203622 2011-02-23 kinaba: } 13b7203622 2011-02-23 kinaba: 13b7203622 2011-02-23 kinaba: } while( len > 0 ); 13b7203622 2011-02-23 kinaba: 13b7203622 2011-02-23 kinaba: if( prgr_read==0xffffffff ) 13b7203622 2011-02-23 kinaba: return false; 13b7203622 2011-02-23 kinaba: 13b7203622 2011-02-23 kinaba: // 8block境界に揃える 13b7203622 2011-02-23 kinaba: if( mask != 1 ) 13b7203622 2011-02-23 kinaba: { 13b7203622 2011-02-23 kinaba: while( mask<<=1 ) 13b7203622 2011-02-23 kinaba: code[codeptr++] = 0; 13b7203622 2011-02-23 kinaba: out.write( code, codeptr ); 13b7203622 2011-02-23 kinaba: } 13b7203622 2011-02-23 kinaba: 13b7203622 2011-02-23 kinaba: return true; 13b7203622 2011-02-23 kinaba: } 13b7203622 2011-02-23 kinaba: