Differences From Artifact [9075347c70b2342c]:
- File
src/bga_melter.d
- 2011-02-23 12:53:16 - part of checkin [c2b7a98c21] on branch trunk - Initial import (user: kinaba) [annotate]
To Artifact [3b6f189d5603825c]:
- File
src/bga_melter.d
- 2015-04-21 10:46:55 - part of checkin [4e2933c620] on branch trunk - Rebased to the latest verson dmd 2.067. Not yet verified the outcome. (user: kinaba) [annotate]
> 1 private import win32.windows;
1 private import std.string; | 2 private import std.string;
2 private import std.file; 3 private import std.file;
3 private import std.c.stdio; 4 private import std.c.stdio;
> 5 private import std.string;
4 private import etc.c.zlib; 6 private import etc.c.zlib;
5 private import win32.ansi.windows; <
6 private import libbz2.bzlib; 7 private import libbz2.bzlib;
7 private import util; 8 private import util;
8 9
9 //---------------------------------------------------------------- 10 //----------------------------------------------------------------
10 // Bga書庫のファイルヘッダ形式 11 // Bga書庫のファイルヘッダ形式
11 //---------------------------------------------------------------- 12 //----------------------------------------------------------------
12 13
................................................................................................................................................................................
23 ubyte header_type; // ヘッダの種類( 現在は常に 0 ) 24 ubyte header_type; // ヘッダの種類( 現在は常に 0 )
24 ushort arc_type; // アーカイブタイプ 25 ushort arc_type; // アーカイブタイプ
25 // 0:(ext==↓?非圧縮:圧縮) 1:圧縮 2:非圧縮 26 // 0:(ext==↓?非圧縮:圧縮) 1:圧縮 2:非圧縮
26 // .ARC, .ARJ, .BZ2, .BZA, .CAB, .GZ, .GZA, 27 // .ARC, .ARJ, .BZ2, .BZA, .CAB, .GZ, .GZA,
27 // .LZS, .PAK, .RAR, .TAZ, .TBZ, .TGZ, .Z, 28 // .LZS, .PAK, .RAR, .TAZ, .TBZ, .TGZ, .Z,
28 ushort dir_name_len; // ディレクトリ名の長さ 29 ushort dir_name_len; // ディレクトリ名の長さ
29 ushort file_name_len; // ファイル名の長さ 30 ushort file_name_len; // ファイル名の長さ
30 char[] fname; // dir_name_len + file_name_len ( no '\0' ) | 31 string fname; // dir_name_len + file_name_len ( no '\0' )
31 } 32 }
32 33
33 //---------------------------------------------------------------- 34 //----------------------------------------------------------------
34 // エラー発生時に投げる例外 35 // エラー発生時に投げる例外
35 //---------------------------------------------------------------- 36 //----------------------------------------------------------------
36 37
37 class BgaMelterError : Error 38 class BgaMelterError : Error
................................................................................................................................................................................
90 } 91 }
91 92
92 class Filep 93 class Filep
93 { 94 {
94 private FILE* fp; 95 private FILE* fp;
95 private this( FILE* p ) { fp = p; } 96 private this( FILE* p ) { fp = p; }
96 97
97 static Filep open( char[] filename, bool read ) | 98 static Filep open( string filename, bool read )
98 { 99 {
99 FILE* fp = fopen( toStringz(filename), read?"rb":"wb" ); 100 FILE* fp = fopen( toStringz(filename), read?"rb":"wb" );
100 return (fp ? new Filep(fp) : null); 101 return (fp ? new Filep(fp) : null);
101 } 102 }
102 103
103 int dup_han() 104 int dup_han()
104 { 105 {
................................................................................................................................................................................
106 lseek( fd, cur(), 0 ); 107 lseek( fd, cur(), 0 );
107 return fd; 108 return fd;
108 } 109 }
109 110
110 void[] read( int siz ) 111 void[] read( int siz )
111 { 112 {
112 char[] buf; buf.length = siz; 113 char[] buf; buf.length = siz;
113 int rsiz = fread( buf, 1, siz, fp ); | 114 int rsiz = fread( buf.ptr, 1, siz, fp );
114 if( rsiz < 0 ) 115 if( rsiz < 0 )
115 throw new BgaMelterError(ERROR_FILE_OPEN); 116 throw new BgaMelterError(ERROR_FILE_OPEN);
116 buf.length = rsiz; 117 buf.length = rsiz;
117 return buf; 118 return buf;
118 } 119 }
119 120
120 void write( void[] buf ) 121 void write( void[] buf )
121 { 122 {
122 while( buf.length > 0 ) 123 while( buf.length > 0 )
123 { 124 {
124 int rsiz = fwrite( buf, 1, buf.length, fp ); | 125 int rsiz = fwrite( buf.ptr, 1, buf.length, fp );
125 if( rsiz < 0 ) return; 126 if( rsiz < 0 ) return;
126 buf = buf[rsiz .. length]; | 127 buf = buf[rsiz .. $];
127 } 128 }
128 } 129 }
129 130
130 int cur() 131 int cur()
131 { 132 {
132 return ftell(fp); 133 return ftell(fp);
133 } 134 }
................................................................................................................................................................................
151 152
152 //---------------------------------------------------------------- 153 //----------------------------------------------------------------
153 // メインクラス 154 // メインクラス
154 //---------------------------------------------------------------- 155 //----------------------------------------------------------------
155 156
156 class BgaMelter 157 class BgaMelter
157 { 158 {
158 alias BgaAnswer delegate(inout BgaHeader) FileHandler; | 159 alias BgaAnswer delegate(ref BgaHeader) FileHandler;
159 alias BgaAnswer delegate(int, int) ProgressHandler; 160 alias BgaAnswer delegate(int, int) ProgressHandler;
160 161
161 private Filep fp = null; 162 private Filep fp = null;
162 163
163 this( char[] arc_name ) | 164 this( string arc_name )
164 { 165 {
165 fp = Filep.open( arc_name, true ); 166 fp = Filep.open( arc_name, true );
166 if( fp is null ) 167 if( fp is null )
167 throw new BgaMelterError(ERROR_FILE_OPEN); 168 throw new BgaMelterError(ERROR_FILE_OPEN);
168 } 169 }
169 170
170 void close() 171 void close()
................................................................................................................................................................................
212 bContinue = GzDec( hdr.compresse 213 bContinue = GzDec( hdr.compresse
213 else if( hdr.method == "BZ2\0" ) 214 else if( hdr.method == "BZ2\0" )
214 bContinue = BzDec( hdr.original_ 215 bContinue = BzDec( hdr.original_
215 216
216 // 閉じて属性設定 217 // 閉じて属性設定
217 outf.close(); 218 outf.close();
218 dosSetFTime( hdr.fname, hdr.date, hdr.ti 219 dosSetFTime( hdr.fname, hdr.date, hdr.ti
219 SetFileAttributes( hdr.fname, hdr.attrib | 220 SetFileAttributesA( toStringz(hdr.fname)
220 if( !bContinue ) 221 if( !bContinue )
221 return; 222 return;
222 } 223 }
223 finally { fp.seek_to(nextpos); } 224 finally { fp.seek_to(nextpos); }
224 } 225 }
225 } 226 }
226 finally { close(); } 227 finally { close(); }
................................................................................................................................................................................
230 { 231 {
231 int cn = c; 232 int cn = c;
232 return (cn>=0x80 ? cn|0xffffff00 : cn); 233 return (cn>=0x80 ? cn|0xffffff00 : cn);
233 } 234 }
234 235
235 private int find_header() 236 private int find_header()
236 { 237 {
237 char[] dat = cast(char[]) fp.read(0x10000); | 238 string dat = cast(string) fp.read(0x10000);
238 239
239 for( int i=0; i<dat.length-28; ++i ) 240 for( int i=0; i<dat.length-28; ++i )
240 { 241 {
241 if( dat[i+4]!='G' && dat[i+4]!='B' ) continue; 242 if( dat[i+4]!='G' && dat[i+4]!='B' ) continue;
242 if( dat[i+5]!='Z' ) continue; 243 if( dat[i+5]!='Z' ) continue;
243 if( dat[i+6]!='I' && dat[i+6]!='2' ) continue; 244 if( dat[i+6]!='I' && dat[i+6]!='2' ) continue;
244 if( dat[i+7]!='P' && dat[i+7]!='\0') continue; 245 if( dat[i+7]!='P' && dat[i+7]!='\0') continue;
................................................................................................................................................................................
256 257
257 return -1; 258 return -1;
258 } 259 }
259 260
260 private bool read_header( out BgaHeader hdr ) 261 private bool read_header( out BgaHeader hdr )
261 { 262 {
262 // リトルエンディアンを仮定。ヘッダ読み込み 263 // リトルエンディアンを仮定。ヘッダ読み込み
263 char[] buf = cast(char[]) fp.read(28); | 264 string buf = cast(string) fp.read(28);
264 if( buf.length < 28 ) return false; 265 if( buf.length < 28 ) return false;
265 buf.length = BgaHeader.sizeof; 266 buf.length = BgaHeader.sizeof;
266 hdr = (cast(BgaHeader[]) buf)[0]; 267 hdr = (cast(BgaHeader[]) buf)[0];
267 hdr.fname = ""; 268 hdr.fname = "";
268 269
269 // ファイル名 270 // ファイル名
270 hdr.fname = cast(char[]) fp.read(hdr.dir_name_len + hdr.file_nam | 271 hdr.fname = cast(string) fp.read(hdr.dir_name_len + hdr.file_nam
271 if( hdr.fname.length < hdr.dir_name_len + hdr.file_name_len ) re 272 if( hdr.fname.length < hdr.dir_name_len + hdr.file_name_len ) re
272 273
273 // チェックサム 274 // チェックサム
274 int sum = 0; 275 int sum = 0;
275 for( int i=4; i!=28; ++i ) sum += signed_char(buf[i]); 276 for( int i=4; i!=28; ++i ) sum += signed_char(buf[i]);
276 foreach( char c ; hdr.fname ) sum += signed_char(c); 277 foreach( char c ; hdr.fname ) sum += signed_char(c);
277 return (sum == hdr.checksum); 278 return (sum == hdr.checksum);
278 } 279 }
279 280
280 private bool is_compressed( inout BgaHeader hdr ) // inout=just for opti | 281 private bool is_compressed( ref BgaHeader hdr ) // ref=just for optimiza
281 { 282 {
282 // ヘッダから、ファイルが圧縮格納されているかどうかを判定 283 // ヘッダから、ファイルが圧縮格納されているかどうかを判定
283 if( hdr.arc_type==2 ) 284 if( hdr.arc_type==2 )
284 return false; 285 return false;
285 if( hdr.arc_type==0 && hdr.compressed_size==hdr.original_size ) 286 if( hdr.arc_type==0 && hdr.compressed_size==hdr.original_size )
286 { 287 {
287 int x = rfind( hdr.fname, '.' ); | 288 int x = hdr.fname.lastIndexOf('.');
288 if( x == -1 ) 289 if( x == -1 )
289 return true; 290 return true;
290 char[] ext = tolower(hdr.fname[x+1 .. length]); | 291 string ext = toLower(hdr.fname[x+1 .. $]);
291 if( ext=="arc" || ext=="arj" || ext=="bz2" || ext=="bza" 292 if( ext=="arc" || ext=="arj" || ext=="bz2" || ext=="bza"
292 || ext=="cab" || ext=="gz" || ext=="gza" || ext=="lzh" 293 || ext=="cab" || ext=="gz" || ext=="gza" || ext=="lzh"
293 || ext=="lzs" || ext=="pak" || ext=="rar" || ext=="taz" 294 || ext=="lzs" || ext=="pak" || ext=="rar" || ext=="taz"
294 || ext=="tbz" || ext=="tgz" || ext=="z" || ext=="zip" 295 || ext=="tbz" || ext=="tgz" || ext=="z" || ext=="zip"
295 || ext=="zoo" ) 296 || ext=="zoo" )
296 return false; 297 return false;
297 } 298 }
298 return true; 299 return true;
299 } 300 }
300 301
301 static char[] pathMake( char[] path ) | 302 static string pathMake( string path )
302 { 303 {
303 char* ps = toStringz(path); | 304 char* ps = cast(char*)toStringz(path);
304 for(char* p=ps;;) 305 for(char* p=ps;;)
305 { 306 {
306 for(; *p!=0&&*p!='\\'&&*p!='/'; p=CharNext(p)) {} | 307 for(; *p!=0&&*p!='\\'&&*p!='/'; p=CharNextA(p)) {}
307 if( *p==0 ) 308 if( *p==0 )
308 break; 309 break;
309 CreateDirectory( toStringz(ps[0..(p-ps)]), null ); | 310 CreateDirectoryA( toStringz(ps[0..(p-ps)]), null );
310 ++p; 311 ++p;
311 } 312 }
312 return path; 313 return path;
313 } 314 }
314 315
315 enum { BUFSIZ = 65536 } 316 enum { BUFSIZ = 65536 }
316 317
................................................................................................................................................................................
317 private bool NcDec( uint usiz, Filep outf, ProgressHandler ph ) 318 private bool NcDec( uint usiz, Filep outf, ProgressHandler ph )
318 { 319 {
319 uint init_usiz = usiz; 320 uint init_usiz = usiz;
320 321
321 // 非圧縮。コピーするだけ 322 // 非圧縮。コピーするだけ
322 while( usiz ) 323 while( usiz )
323 { 324 {
324 char[] r = cast(char[]) fp.read( BUFSIZ<usiz?BUFSIZ:usiz | 325 string r = cast(string) fp.read( BUFSIZ<usiz?BUFSIZ:usiz
325 usiz -= r.length; 326 usiz -= r.length;
326 outf.write(r); | 327 outf.write(cast(char[])r);
327 328
328 // dlg 329 // dlg
329 if( BgaAnswer.Abort==ph(init_usiz-usiz,usiz) ) return fa 330 if( BgaAnswer.Abort==ph(init_usiz-usiz,usiz) ) return fa
330 } 331 }
331 332
332 // dlg 333 // dlg
333 if( BgaAnswer.Abort==ph(init_usiz-usiz,usiz) ) return false; 334 if( BgaAnswer.Abort==ph(init_usiz-usiz,usiz) ) return false;
................................................................................................................................................................................
346 347
347 // zlib準備 348 // zlib準備
348 z_stream zs; 349 z_stream zs;
349 zs.zalloc = null; 350 zs.zalloc = null;
350 zs.zfree = null; 351 zs.zfree = null;
351 352
352 // 出力バッファ 353 // 出力バッファ
353 zs.next_out = outbuf; | 354 zs.next_out = outbuf.ptr;
354 zs.avail_out = outbuf.length; 355 zs.avail_out = outbuf.length;
355 356
356 // 入力バッファ 357 // 入力バッファ
357 inbuf = cast(ubyte[]) fp.read( csiz<65536 ? csiz : 65536 ); 358 inbuf = cast(ubyte[]) fp.read( csiz<65536 ? csiz : 65536 );
358 csiz -= inbuf.length; 359 csiz -= inbuf.length;
359 zs.next_in = inbuf; | 360 zs.next_in = inbuf.ptr;
360 zs.avail_in = inbuf.length; 361 zs.avail_in = inbuf.length;
361 362
362 // スタート 363 // スタート
363 inflateInit2( &zs, -15 ); 364 inflateInit2( &zs, -15 );
364 try { 365 try {
365 366
366 // 書庫から入力し終わるまでループ 367 // 書庫から入力し終わるまでループ
................................................................................................................................................................................
375 if( !csiz ) 376 if( !csiz )
376 break; 377 break;
377 378
378 if( zs.avail_in<=0 ) 379 if( zs.avail_in<=0 )
379 { 380 {
380 inbuf = cast(ubyte[]) fp.read( csiz<6553 381 inbuf = cast(ubyte[]) fp.read( csiz<6553
381 csiz -= inbuf.length; 382 csiz -= inbuf.length;
382 zs.next_in = inbuf; | 383 zs.next_in = inbuf.ptr;
383 zs.avail_in = inbuf.length; 384 zs.avail_in = inbuf.length;
384 385
385 if( inbuf.length==0 ) 386 if( inbuf.length==0 )
386 { 387 {
387 err = Z_STREAM_END; 388 err = Z_STREAM_END;
388 csiz = 0; 389 csiz = 0;
389 break; 390 break;
................................................................................................................................................................................
391 } 392 }
392 } 393 }
393 394
394 int written = outbuf.length - zs.avail_out; 395 int written = outbuf.length - zs.avail_out;
395 if( usiz < written ) written = usiz; 396 if( usiz < written ) written = usiz;
396 usiz -= written; 397 usiz -= written;
397 outf.write( outbuf[0..written] ); 398 outf.write( outbuf[0..written] );
398 zs.next_out = outbuf; | 399 zs.next_out = outbuf.ptr;
399 zs.avail_out = outbuf.length; 400 zs.avail_out = outbuf.length;
400 401
401 // dlg 402 // dlg
402 if( BgaAnswer.Abort==ph(init_usiz-usiz,usiz) ) return fa 403 if( BgaAnswer.Abort==ph(init_usiz-usiz,usiz) ) return fa
403 } 404 }
404 405
405 // 出力残しを無くす。 406 // 出力残しを無くす。
................................................................................................................................................................................
409 if( err!=Z_STREAM_END && err!=Z_OK ) 410 if( err!=Z_STREAM_END && err!=Z_OK )
410 break; 411 break;
411 412
412 int written = outbuf.length - zs.avail_out; 413 int written = outbuf.length - zs.avail_out;
413 if( usiz < written ) written = usiz; 414 if( usiz < written ) written = usiz;
414 usiz -= written; 415 usiz -= written;
415 outf.write( outbuf[0..written] ); 416 outf.write( outbuf[0..written] );
416 zs.next_out = outbuf; | 417 zs.next_out = outbuf.ptr;
417 zs.avail_out = outbuf.length; 418 zs.avail_out = outbuf.length;
418 419
419 // dlg 420 // dlg
420 if( BgaAnswer.Abort==ph(init_usiz-usiz,usiz) ) return fa 421 if( BgaAnswer.Abort==ph(init_usiz-usiz,usiz) ) return fa
421 } 422 }
422 423
423 // 終了 424 // 終了
................................................................................................................................................................................
430 431
431 private bool BzDec( uint usiz, Filep outf, ProgressHandler ph ) 432 private bool BzDec( uint usiz, Filep outf, ProgressHandler ph )
432 { 433 {
433 uint init_usiz = usiz; 434 uint init_usiz = usiz;
434 435
435 // libbz2で展開 436 // libbz2で展開
436 int err; 437 int err;
437 BZFILE* b = BZ2_bzReadOpen( &err, fp.get_fp(), 0, 0, NULL, 0 ); | 438 BZFILE* b = BZ2_bzReadOpen( &err, fp.get_fp(), 0, 0, null, 0 );
438 if( err!=BZ_OK || b is null ) 439 if( err!=BZ_OK || b is null )
439 return true; 440 return true;
440 441
441 try 442 try
442 { 443 {
443 char[] buf; buf.length = BUFSIZ; 444 char[] buf; buf.length = BUFSIZ;
444 int len; 445 int len;
445 while( 0<(len=BZ2_bzRead( &err, b, buf, BUFSIZ<usiz?BUFS | 446 while( 0<(len=BZ2_bzRead( &err, b, buf.ptr, BUFSIZ<usiz?
446 { 447 {
447 outf.write( buf[0..len] ); 448 outf.write( buf[0..len] );
448 usiz -= len; 449 usiz -= len;
449 if( err != BZ_OK ) 450 if( err != BZ_OK )
450 break; 451 break;
451 452
452 // dlg 453 // dlg