Mercurial > audlegacy-plugins
diff src/console/Data_Reader.cxx @ 316:fb513e10174e trunk
[svn] - merge libconsole-blargg into mainline libconsole:
+ obsoletes plugins-ugly:sapplug
author | nenolod |
---|---|
date | Thu, 30 Nov 2006 19:54:33 -0800 |
parents | |
children | 986f098da058 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/console/Data_Reader.cxx Thu Nov 30 19:54:33 2006 -0800 @@ -0,0 +1,316 @@ +// File_Extractor 0.4.0. http://www.slack.net/~ant/ + +#include "Data_Reader.h" + +#include <assert.h> +#include <string.h> +#include <stdio.h> + +/* Copyright (C) 2005-2006 Shay Green. This module is free software; you +can redistribute it and/or modify it under the terms of the GNU Lesser +General Public License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. This +module is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more +details. You should have received a copy of the GNU Lesser General Public +License along with this module; if not, write to the Free Software Foundation, +Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ + +const char Data_Reader::eof_error [] = "Unexpected end of file"; + +typedef Data_Reader::error_t error_t; + +error_t Data_Reader::read( void* p, long s ) +{ + long result = read_avail( p, s ); + if ( result != s ) + { + if ( result >= 0 && result < s ) + return eof_error; + + return "Read error"; + } + + return 0; +} + +error_t Data_Reader::skip( long count ) +{ + char buf [512]; + while ( count ) + { + long n = sizeof buf; + if ( n > count ) + n = count; + count -= n; + error_t err = read( buf, n ); + if ( err ) + return err; + } + return 0; +} + +long File_Reader::remain() const { return size() - tell(); } + +error_t File_Reader::skip( long n ) +{ + assert( n >= 0 ); + return n ? seek( tell() + n ) : 0; +} + +// Subset_Reader + +Subset_Reader::Subset_Reader( Data_Reader* dr, long size ) +{ + in = dr; + remain_ = dr->remain(); + if ( remain_ > size ) + remain_ = size; +} + +long Subset_Reader::remain() const { return remain_; } + +long Subset_Reader::read_avail( void* p, long s ) +{ + if ( s > remain_ ) + s = remain_; + remain_ -= s; + return in->read_avail( p, s ); +} + +// Remaining_Reader + +Remaining_Reader::Remaining_Reader( void const* h, long size, Data_Reader* r ) +{ + header = (char const*) h; + header_end = header + size; + in = r; +} + +long Remaining_Reader::remain() const { return header_end - header + in->remain(); } + +long Remaining_Reader::read_first( void* out, long count ) +{ + long first = header_end - header; + if ( first ) + { + if ( first > count ) + first = count; + void const* in = header; + header += first; + memcpy( out, in, first ); + } + return first; +} + +long Remaining_Reader::read_avail( void* out, long count ) +{ + long first = read_first( out, count ); + long remain = count - first; + if ( remain ) + { + remain = in->read_avail( (char*) out + first, remain ); + if ( remain <= 0 ) + return remain; + } + return first + remain; +} + +error_t Remaining_Reader::read( void* out, long count ) +{ + long first = read_first( out, count ); + long remain = count - first; + if ( !remain ) + return 0; + return in->read( (char*) out + first, remain ); +} + +// Mem_File_Reader + +Mem_File_Reader::Mem_File_Reader( const void* p, long s ) : + begin( (const char*) p ), + size_( s ) +{ + pos = 0; +} + +long Mem_File_Reader::size() const { return size_; } + +long Mem_File_Reader::read_avail( void* p, long s ) +{ + long r = remain(); + if ( s > r ) + s = r; + memcpy( p, begin + pos, s ); + pos += s; + return s; +} + +long Mem_File_Reader::tell() const { return pos; } + +error_t Mem_File_Reader::seek( long n ) +{ + if ( n > size_ ) + return eof_error; + pos = n; + return 0; +} + +// Std_File_Reader + +Std_File_Reader::Std_File_Reader() : file_( 0 ) { } + +Std_File_Reader::~Std_File_Reader() { close(); } + +error_t Std_File_Reader::open( const char* path ) +{ + file_ = fopen( path, "rb" ); + if ( !file_ ) + return "Couldn't open file"; + return 0; +} + +long Std_File_Reader::size() const +{ + long pos = tell(); + fseek( (FILE*) file_, 0, SEEK_END ); + long result = tell(); + fseek( (FILE*) file_, pos, SEEK_SET ); + return result; +} + +long Std_File_Reader::read_avail( void* p, long s ) +{ + return fread( p, 1, s, (FILE*) file_ ); +} + +error_t Std_File_Reader::read( void* p, long s ) +{ + if ( s == (long) fread( p, 1, s, (FILE*) file_ ) ) + return 0; + if ( feof( (FILE*) file_ ) ) + return eof_error; + return "Couldn't read from file"; +} + +long Std_File_Reader::tell() const { return ftell( (FILE*) file_ ); } + +error_t Std_File_Reader::seek( long n ) +{ + if ( !fseek( (FILE*) file_, n, SEEK_SET ) ) + return 0; + if ( n > size() ) + return eof_error; + return "Error seeking in file"; +} + +void Std_File_Reader::close() +{ + if ( file_ ) + { + fclose( (FILE*) file_ ); + file_ = 0; + } +} + +// Callback_Reader + +Callback_Reader::Callback_Reader( callback_t c, long size, void* d ) : + callback( c ), + data( d ) +{ + remain_ = size; +} + +long Callback_Reader::remain() const { return remain_; } + +long Callback_Reader::read_avail( void* out, long count ) +{ + if ( count > remain_ ) + count = remain_; + if ( Callback_Reader::read( out, count ) ) + count = -1; + return count; +} + +Callback_Reader::error_t Callback_Reader::read( void* out, long count ) +{ + if ( count > remain_ ) + return eof_error; + return callback( data, out, count ); +} + +// Gzip_File_Reader + +#ifdef HAVE_ZLIB_H + +#include "zlib.h" + +static const char* get_gzip_eof( const char* path, long* eof ) +{ + FILE* file = fopen( path, "rb" ); + if ( !file ) + return "Couldn't open file"; + + unsigned char buf [4]; + if ( fread( buf, 2, 1, file ) == 1 && buf [0] == 0x1F && buf [1] == 0x8B ) + { + fseek( file, -4, SEEK_END ); + fread( buf, 4, 1, file ); + *eof = buf [3] * 0x1000000L + buf [2] * 0x10000L + buf [1] * 0x100L + buf [0]; + } + else + { + fseek( file, 0, SEEK_END ); + *eof = ftell( file ); + } + const char* err = (ferror( file ) || feof( file )) ? "Couldn't get file size" : 0; + fclose( file ); + return err; +} + +Gzip_File_Reader::Gzip_File_Reader() : file_( 0 ) { } + +Gzip_File_Reader::~Gzip_File_Reader() { close(); } + +error_t Gzip_File_Reader::open( const char* path ) +{ + close(); + + error_t err = get_gzip_eof( path, &size_ ); + if ( err ) + return err; + + file_ = gzopen( path, "rb" ); + if ( !file_ ) + return "Couldn't open file"; + + return 0; +} + +long Gzip_File_Reader::size() const { return size_; } + +long Gzip_File_Reader::read_avail( void* p, long s ) { return gzread( file_, p, s ); } + +long Gzip_File_Reader::tell() const { return gztell( file_ ); } + +error_t Gzip_File_Reader::seek( long n ) +{ + if ( gzseek( file_, n, SEEK_SET ) >= 0 ) + return 0; + if ( n > size_ ) + return eof_error; + return "Error seeking in file"; +} + +void Gzip_File_Reader::close() +{ + if ( file_ ) + { + gzclose( file_ ); + file_ = 0; + } +} + +#endif