Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
alexbevi
GitHub Repository: alexbevi/BizHawk
Path: blob/master/quicknes/fex/Data_Reader.cpp
2 views
1
// File_Extractor 1.0.0. http://www.slack.net/~ant/
2
3
#include "Data_Reader.h"
4
5
#include "blargg_endian.h"
6
#include <stdio.h>
7
#include <errno.h>
8
9
/* Copyright (C) 2005-2009 Shay Green. This module is free software; you
10
can redistribute it and/or modify it under the terms of the GNU Lesser
11
General Public License as published by the Free Software Foundation; either
12
version 2.1 of the License, or (at your option) any later version. This
13
module is distributed in the hope that it will be useful, but WITHOUT ANY
14
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
15
FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
16
details. You should have received a copy of the GNU Lesser General Public
17
License along with this module; if not, write to the Free Software Foundation,
18
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
19
20
#include "blargg_source.h"
21
22
// Data_Reader
23
24
blargg_err_t Data_Reader::read( void* p, int n )
25
{
26
assert( n >= 0 );
27
28
if ( n < 0 )
29
return blargg_err_caller;
30
31
if ( n <= 0 )
32
return blargg_ok;
33
34
if ( n > remain() )
35
return blargg_err_file_eof;
36
37
blargg_err_t err = read_v( p, n );
38
if ( !err )
39
remain_ -= n;
40
41
return err;
42
}
43
44
blargg_err_t Data_Reader::read_avail( void* p, int* n_ )
45
{
46
assert( *n_ >= 0 );
47
48
int n = min( (BOOST::uint64_t)(*n_), remain() );
49
*n_ = 0;
50
51
if ( n < 0 )
52
return blargg_err_caller;
53
54
if ( n <= 0 )
55
return blargg_ok;
56
57
blargg_err_t err = read_v( p, n );
58
if ( !err )
59
{
60
remain_ -= n;
61
*n_ = n;
62
}
63
64
return err;
65
}
66
67
blargg_err_t Data_Reader::read_avail( void* p, long* n )
68
{
69
int i = STATIC_CAST(int, *n);
70
blargg_err_t err = read_avail( p, &i );
71
*n = i;
72
return err;
73
}
74
75
blargg_err_t Data_Reader::skip_v( int count )
76
{
77
char buf [512];
78
while ( count )
79
{
80
int n = min( count, (int) sizeof buf );
81
count -= n;
82
RETURN_ERR( read_v( buf, n ) );
83
}
84
return blargg_ok;
85
}
86
87
blargg_err_t Data_Reader::skip( int n )
88
{
89
assert( n >= 0 );
90
91
if ( n < 0 )
92
return blargg_err_caller;
93
94
if ( n <= 0 )
95
return blargg_ok;
96
97
if ( n > remain() )
98
return blargg_err_file_eof;
99
100
blargg_err_t err = skip_v( n );
101
if ( !err )
102
remain_ -= n;
103
104
return err;
105
}
106
107
108
// File_Reader
109
110
blargg_err_t File_Reader::seek( BOOST::uint64_t n )
111
{
112
assert( n >= 0 );
113
114
if ( n < 0 )
115
return blargg_err_caller;
116
117
if ( n == tell() )
118
return blargg_ok;
119
120
if ( n > size() )
121
return blargg_err_file_eof;
122
123
blargg_err_t err = seek_v( n );
124
if ( !err )
125
set_tell( n );
126
127
return err;
128
}
129
130
blargg_err_t File_Reader::skip_v( BOOST::uint64_t n )
131
{
132
return seek_v( tell() + n );
133
}
134
135
136
// Subset_Reader
137
138
Subset_Reader::Subset_Reader( Data_Reader* dr, BOOST::uint64_t size ) :
139
in( dr )
140
{
141
set_remain( min( size, dr->remain() ) );
142
}
143
144
blargg_err_t Subset_Reader::read_v( void* p, int s )
145
{
146
return in->read( p, s );
147
}
148
149
150
// Remaining_Reader
151
152
Remaining_Reader::Remaining_Reader( void const* h, int size, Data_Reader* r ) :
153
in( r )
154
{
155
header = h;
156
header_remain = size;
157
158
set_remain( size + r->remain() );
159
}
160
161
blargg_err_t Remaining_Reader::read_v( void* out, int count )
162
{
163
int first = min( count, header_remain );
164
if ( first )
165
{
166
memcpy( out, header, first );
167
header = STATIC_CAST(char const*, header) + first;
168
header_remain -= first;
169
}
170
171
return in->read( STATIC_CAST(char*, out) + first, count - first );
172
}
173
174
175
// Mem_File_Reader
176
177
Mem_File_Reader::Mem_File_Reader( const void* p, long s ) :
178
begin( STATIC_CAST(const char*, p) )
179
{
180
set_size( s );
181
}
182
183
blargg_err_t Mem_File_Reader::read_v( void* p, int s )
184
{
185
memcpy( p, begin + tell(), s );
186
return blargg_ok;
187
}
188
189
blargg_err_t Mem_File_Reader::seek_v( int )
190
{
191
return blargg_ok;
192
}
193
194
195
// Callback_Reader
196
197
Callback_Reader::Callback_Reader( callback_t c, BOOST::uint64_t s, void* d ) :
198
callback( c ),
199
user_data( d )
200
{
201
set_remain( s );
202
}
203
204
blargg_err_t Callback_Reader::read_v( void* out, int count )
205
{
206
return callback( user_data, out, count );
207
}
208
209
210
// Callback_File_Reader
211
212
Callback_File_Reader::Callback_File_Reader( callback_t c, BOOST::uint64_t s, void* d ) :
213
callback( c ),
214
user_data( d )
215
{
216
set_size( s );
217
}
218
219
blargg_err_t Callback_File_Reader::read_v( void* out, int count )
220
{
221
return callback( user_data, out, count, tell() );
222
}
223
224
blargg_err_t Callback_File_Reader::seek_v( int )
225
{
226
return blargg_ok;
227
}
228
229
static const BOOST::uint8_t mask_tab[6]={0x80,0xE0,0xF0,0xF8,0xFC,0xFE};
230
231
static const BOOST::uint8_t val_tab[6]={0,0xC0,0xE0,0xF0,0xF8,0xFC};
232
233
size_t utf8_char_len_from_header( char p_c )
234
{
235
// what is this?
236
// BOOST::uint8_t c = (BOOST::uint8_t)p_c;
237
238
size_t cnt = 0;
239
for(;;)
240
{
241
if ( ( p_c & mask_tab[cnt] ) == val_tab[cnt] ) break;
242
if ( ++cnt >= 6 ) return 0;
243
}
244
245
return cnt + 1;
246
}
247
248
size_t utf8_decode_char( const char *p_utf8, unsigned & wide, size_t mmax )
249
{
250
const BOOST::uint8_t * utf8 = ( const BOOST::uint8_t* )p_utf8;
251
252
if ( mmax == 0 )
253
{
254
wide = 0;
255
return 0;
256
}
257
258
if ( utf8[0] < 0x80 )
259
{
260
wide = utf8[0];
261
return utf8[0]>0 ? 1 : 0;
262
}
263
if ( mmax > 6 ) mmax = 6;
264
wide = 0;
265
266
unsigned res=0;
267
unsigned n;
268
unsigned cnt=0;
269
for(;;)
270
{
271
if ( ( *utf8 & mask_tab[cnt] ) == val_tab[cnt] ) break;
272
if ( ++cnt >= mmax ) return 0;
273
}
274
cnt++;
275
276
if ( cnt==2 && !( *utf8 & 0x1E ) ) return 0;
277
278
if ( cnt == 1 )
279
res = *utf8;
280
else
281
res = ( 0xFF >> ( cnt + 1 ) ) & *utf8;
282
283
for ( n = 1; n < cnt; n++ )
284
{
285
if ( ( utf8[n] & 0xC0 ) != 0x80 )
286
return 0;
287
if ( !res && n == 2 && !( ( utf8[n] & 0x7F ) >> ( 7 - cnt ) ) )
288
return 0;
289
290
res = ( res << 6 ) | ( utf8[n] & 0x3F );
291
}
292
293
wide = res;
294
295
return cnt;
296
}
297
298
size_t utf8_encode_char( unsigned wide, char * target )
299
{
300
size_t count;
301
302
if ( wide < 0x80 )
303
count = 1;
304
else if ( wide < 0x800 )
305
count = 2;
306
else if ( wide < 0x10000 )
307
count = 3;
308
else if ( wide < 0x200000 )
309
count = 4;
310
else if ( wide < 0x4000000 )
311
count = 5;
312
else if ( wide <= 0x7FFFFFFF )
313
count = 6;
314
else
315
return 0;
316
317
if ( target == 0 )
318
return count;
319
320
switch ( count )
321
{
322
case 6:
323
target[5] = 0x80 | ( wide & 0x3F );
324
wide = wide >> 6;
325
wide |= 0x4000000;
326
case 5:
327
target[4] = 0x80 | ( wide & 0x3F );
328
wide = wide >> 6;
329
wide |= 0x200000;
330
case 4:
331
target[3] = 0x80 | ( wide & 0x3F );
332
wide = wide >> 6;
333
wide |= 0x10000;
334
case 3:
335
target[2] = 0x80 | ( wide & 0x3F );
336
wide = wide >> 6;
337
wide |= 0x800;
338
case 2:
339
target[1] = 0x80 | ( wide & 0x3F );
340
wide = wide >> 6;
341
wide |= 0xC0;
342
case 1:
343
target[0] = wide;
344
}
345
346
return count;
347
}
348
349
size_t utf16_encode_char( unsigned cur_wchar, blargg_wchar_t * out )
350
{
351
if ( cur_wchar < 0x10000 )
352
{
353
if ( out ) *out = (blargg_wchar_t) cur_wchar; return 1;
354
}
355
else if ( cur_wchar < ( 1 << 20 ) )
356
{
357
unsigned c = cur_wchar - 0x10000;
358
//MSDN:
359
//The first (high) surrogate is a 16-bit code value in the range U+D800 to U+DBFF. The second (low) surrogate is a 16-bit code value in the range U+DC00 to U+DFFF. Using surrogates, Unicode can support over one million characters. For more details about surrogates, refer to The Unicode Standard, version 2.0.
360
if ( out )
361
{
362
out[0] = ( blargg_wchar_t )( 0xD800 | ( 0x3FF & ( c >> 10 ) ) );
363
out[1] = ( blargg_wchar_t )( 0xDC00 | ( 0x3FF & c ) ) ;
364
}
365
return 2;
366
}
367
else
368
{
369
if ( out ) *out = '?'; return 1;
370
}
371
}
372
373
size_t utf16_decode_char( const blargg_wchar_t * p_source, unsigned * p_out, size_t p_source_length )
374
{
375
if ( p_source_length == 0 ) return 0;
376
else if ( p_source_length == 1 )
377
{
378
*p_out = p_source[0];
379
return 1;
380
}
381
else
382
{
383
size_t retval = 0;
384
unsigned decoded = p_source[0];
385
if ( decoded != 0 )
386
{
387
retval = 1;
388
if ( ( decoded & 0xFC00 ) == 0xD800 )
389
{
390
unsigned low = p_source[1];
391
if ( ( low & 0xFC00 ) == 0xDC00 )
392
{
393
decoded = 0x10000 + ( ( ( decoded & 0x3FF ) << 10 ) | ( low & 0x3FF ) );
394
retval = 2;
395
}
396
}
397
}
398
*p_out = decoded;
399
return retval;
400
}
401
}
402
403
// Converts wide-character path to UTF-8. Free result with free(). Only supported on Windows.
404
char* blargg_to_utf8( const blargg_wchar_t* wpath )
405
{
406
if ( wpath == NULL )
407
return NULL;
408
409
size_t needed = 0;
410
size_t mmax = blargg_wcslen( wpath );
411
if ( mmax <= 0 )
412
return NULL;
413
414
size_t ptr = 0;
415
while ( ptr < mmax )
416
{
417
unsigned wide = 0;
418
size_t char_len = utf16_decode_char( wpath + ptr, &wide, mmax - ptr );
419
if ( !char_len ) break;
420
ptr += char_len;
421
needed += utf8_encode_char( wide, 0 );
422
}
423
if ( needed <= 0 )
424
return NULL;
425
426
char* path = (char*) calloc( needed + 1, 1 );
427
if ( path == NULL )
428
return NULL;
429
430
ptr = 0;
431
size_t actual = 0;
432
while ( ptr < mmax && actual < needed )
433
{
434
unsigned wide = 0;
435
size_t char_len = utf16_decode_char( wpath + ptr, &wide, mmax - ptr );
436
if ( !char_len ) break;
437
ptr += char_len;
438
actual += utf8_encode_char( wide, path + actual );
439
}
440
441
if ( actual == 0 )
442
{
443
free( path );
444
return NULL;
445
}
446
447
assert( actual == needed );
448
return path;
449
}
450
451
// Converts UTF-8 path to wide-character. Free result with free() Only supported on Windows.
452
blargg_wchar_t* blargg_to_wide( const char* path )
453
{
454
if ( path == NULL )
455
return NULL;
456
457
size_t mmax = strlen( path );
458
if ( mmax <= 0 )
459
return NULL;
460
461
size_t needed = 0;
462
size_t ptr = 0;
463
while ( ptr < mmax )
464
{
465
unsigned wide = 0;
466
size_t char_len = utf8_decode_char( path + ptr, wide, mmax - ptr );
467
if ( !char_len ) break;
468
ptr += char_len;
469
needed += utf16_encode_char( wide, 0 );
470
}
471
if ( needed <= 0 )
472
return NULL;
473
474
blargg_wchar_t* wpath = (blargg_wchar_t*) calloc( needed + 1, sizeof *wpath );
475
if ( wpath == NULL )
476
return NULL;
477
478
ptr = 0;
479
size_t actual = 0;
480
while ( ptr < mmax && actual < needed )
481
{
482
unsigned wide = 0;
483
size_t char_len = utf8_decode_char( path + ptr, wide, mmax - ptr );
484
if ( !char_len ) break;
485
ptr += char_len;
486
actual += utf16_encode_char( wide, wpath + actual );
487
}
488
if ( actual == 0 )
489
{
490
free( wpath );
491
return NULL;
492
}
493
494
assert( actual == needed );
495
return wpath;
496
}
497
498
#ifdef _WIN32
499
500
static FILE* blargg_fopen( const char path [], const char mode [] )
501
{
502
FILE* file = NULL;
503
blargg_wchar_t* wmode = NULL;
504
blargg_wchar_t* wpath = NULL;
505
506
wpath = blargg_to_wide( path );
507
if ( wpath )
508
{
509
wmode = blargg_to_wide( mode );
510
if ( wmode )
511
file = _wfopen( wpath, wmode );
512
}
513
514
// Save and restore errno in case free() clears it
515
int saved_errno = errno;
516
free( wmode );
517
free( wpath );
518
errno = saved_errno;
519
520
return file;
521
}
522
523
#else
524
525
static inline FILE* blargg_fopen( const char path [], const char mode [] )
526
{
527
return fopen( path, mode );
528
}
529
530
#endif
531
532
533
// Std_File_Reader
534
535
Std_File_Reader::Std_File_Reader()
536
{
537
file_ = NULL;
538
}
539
540
Std_File_Reader::~Std_File_Reader()
541
{
542
close();
543
}
544
545
static blargg_err_t blargg_fopen( FILE** out, const char path [] )
546
{
547
errno = 0;
548
*out = blargg_fopen( path, "rb" );
549
if ( !*out )
550
{
551
#ifdef ENOENT
552
if ( errno == ENOENT )
553
return blargg_err_file_missing;
554
#endif
555
#ifdef ENOMEM
556
if ( errno == ENOMEM )
557
return blargg_err_memory;
558
#endif
559
return blargg_err_file_read;
560
}
561
562
return blargg_ok;
563
}
564
565
static blargg_err_t blargg_fsize( FILE* f, long* out )
566
{
567
if ( fseek( f, 0, SEEK_END ) )
568
return blargg_err_file_io;
569
570
*out = ftell( f );
571
if ( *out < 0 )
572
return blargg_err_file_io;
573
574
if ( fseek( f, 0, SEEK_SET ) )
575
return blargg_err_file_io;
576
577
return blargg_ok;
578
}
579
580
blargg_err_t Std_File_Reader::open( const char path [] )
581
{
582
close();
583
584
FILE* f;
585
RETURN_ERR( blargg_fopen( &f, path ) );
586
587
long s;
588
blargg_err_t err = blargg_fsize( f, &s );
589
if ( err )
590
{
591
fclose( f );
592
return err;
593
}
594
595
file_ = f;
596
set_size( s );
597
598
return blargg_ok;
599
}
600
601
void Std_File_Reader::make_unbuffered()
602
{
603
if ( setvbuf( STATIC_CAST(FILE*, file_), NULL, _IONBF, 0 ) )
604
check( false ); // shouldn't fail, but OK if it does
605
}
606
607
blargg_err_t Std_File_Reader::read_v( void* p, int s )
608
{
609
if ( (size_t) s != fread( p, 1, s, STATIC_CAST(FILE*, file_) ) )
610
{
611
// Data_Reader's wrapper should prevent EOF
612
check( !feof( STATIC_CAST(FILE*, file_) ) );
613
614
return blargg_err_file_io;
615
}
616
617
return blargg_ok;
618
}
619
620
#ifdef __CELLOS_LV2__
621
int
622
fseeko(FILE *stream, off_t pos, int whence)
623
{
624
return fseek(stream, (long)pos, whence);
625
}
626
#endif
627
628
blargg_err_t Std_File_Reader::seek_v( BOOST::uint64_t n )
629
{
630
#ifdef _WIN32
631
if ( fseek( STATIC_CAST(FILE*, file_), n, SEEK_SET ) )
632
#else
633
if ( fseeko( STATIC_CAST(FILE*, file_), n, SEEK_SET ) )
634
#endif
635
{
636
// Data_Reader's wrapper should prevent EOF
637
check( !feof( STATIC_CAST(FILE*, file_) ) );
638
639
return blargg_err_file_io;
640
}
641
642
return blargg_ok;
643
}
644
645
void Std_File_Reader::close()
646
{
647
if ( file_ )
648
{
649
fclose( STATIC_CAST(FILE*, file_) );
650
file_ = NULL;
651
}
652
}
653
654
655
// Gzip_File_Reader
656
657
#ifndef __LIBRETRO__
658
#ifdef HAVE_ZLIB_H
659
660
#include "zlib.h"
661
662
static const char* get_gzip_eof( const char path [], long* eof )
663
{
664
FILE* file;
665
RETURN_ERR( blargg_fopen( &file, path ) );
666
667
int const h_size = 4;
668
unsigned char h [h_size];
669
670
// read four bytes to ensure that we can seek to -4 later
671
if ( fread( h, 1, h_size, file ) != (size_t) h_size || h[0] != 0x1F || h[1] != 0x8B )
672
{
673
// Not gzipped
674
if ( ferror( file ) )
675
return blargg_err_file_io;
676
677
if ( fseek( file, 0, SEEK_END ) )
678
return blargg_err_file_io;
679
680
*eof = ftell( file );
681
if ( *eof < 0 )
682
return blargg_err_file_io;
683
}
684
else
685
{
686
// Gzipped; get uncompressed size from end
687
if ( fseek( file, -h_size, SEEK_END ) )
688
return blargg_err_file_io;
689
690
if ( fread( h, 1, h_size, file ) != (size_t) h_size )
691
return blargg_err_file_io;
692
693
*eof = get_le32( h );
694
}
695
696
if ( fclose( file ) )
697
check( false );
698
699
return blargg_ok;
700
}
701
702
Gzip_File_Reader::Gzip_File_Reader()
703
{
704
file_ = NULL;
705
}
706
707
Gzip_File_Reader::~Gzip_File_Reader()
708
{
709
close();
710
}
711
712
blargg_err_t Gzip_File_Reader::open( const char path [] )
713
{
714
close();
715
716
long s;
717
RETURN_ERR( get_gzip_eof( path, &s ) );
718
719
file_ = gzopen( path, "rb" );
720
if ( !file_ )
721
return blargg_err_file_read;
722
723
set_size( s );
724
return blargg_ok;
725
}
726
727
static blargg_err_t convert_gz_error( gzFile file )
728
{
729
int err;
730
gzerror( file, &err );
731
732
switch ( err )
733
{
734
case Z_STREAM_ERROR: break;
735
case Z_DATA_ERROR: return blargg_err_file_corrupt;
736
case Z_MEM_ERROR: return blargg_err_memory;
737
case Z_BUF_ERROR: break;
738
}
739
return blargg_err_internal;
740
}
741
742
blargg_err_t Gzip_File_Reader::read_v( void* p, int s )
743
{
744
int result = gzread( (gzFile) file_, p, s );
745
if ( result != s )
746
{
747
if ( result < 0 )
748
return convert_gz_error( (gzFile) file_ );
749
750
return blargg_err_file_corrupt;
751
}
752
753
return blargg_ok;
754
}
755
756
blargg_err_t Gzip_File_Reader::seek_v( int n )
757
{
758
if ( gzseek( (gzFile) file_, n, SEEK_SET ) < 0 )
759
return convert_gz_error( (gzFile) file_ );
760
761
return blargg_ok;
762
}
763
764
void Gzip_File_Reader::close()
765
{
766
if ( file_ )
767
{
768
if ( gzclose( (gzFile) file_ ) )
769
check( false );
770
file_ = NULL;
771
}
772
}
773
#endif
774
775
#endif
776
777