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