// Lightweight interface for reading data from byte stream12// File_Extractor 1.0.03#ifndef DATA_READER_H4#define DATA_READER_H56#include "blargg_common.h"78/* Some functions accept a long instead of int for convenience where caller has9a long due to some other interface, and would otherwise have to get a warning,10or cast it (and verify that it wasn't outside the range of an int).1112To really support huge (>2GB) files, long isn't a solution, since there's no13guarantee it's more than 32 bits. We'd need to use long long (if available), or14something compiler-specific, and change all places file sizes or offsets are15used. */1617// Supports reading and finding out how many bytes are remaining18class Data_Reader {19public:2021// Reads min(*n,remain()) bytes and sets *n to this number, thus trying to read more22// tham remain() bytes doesn't result in error, just *n being set to remain().23blargg_err_t read_avail( void* p, int* n );24blargg_err_t read_avail( void* p, long* n );2526// Reads exactly n bytes, or returns error if they couldn't ALL be read.27// Reading past end of file results in blargg_err_file_eof.28blargg_err_t read( void* p, int n );2930// Number of bytes remaining until end of file31BOOST::uint64_t remain() const { return remain_; }3233// Reads and discards n bytes. Skipping past end of file results in blargg_err_file_eof.34blargg_err_t skip( int n );3536virtual ~Data_Reader() { }3738private:39// noncopyable40Data_Reader( const Data_Reader& );41Data_Reader& operator = ( const Data_Reader& );4243// Derived interface44protected:45Data_Reader() : remain_( 0 ) { }4647// Sets remain48void set_remain( BOOST::uint64_t n ) { assert( n >= 0 ); remain_ = n; }4950// Do same as read(). Guaranteed that 0 < n <= remain(). Value of remain() is updated51// AFTER this call succeeds, not before. set_remain() should NOT be called from this.52virtual blargg_err_t read_v( void*, int n ) BLARGG_PURE( { (void)n; return blargg_ok; } )5354// Do same as skip(). Guaranteed that 0 < n <= remain(). Default just reads data55// and discards it. Value of remain() is updated AFTER this call succeeds, not56// before. set_remain() should NOT be called from this.57virtual blargg_err_t skip_v( int n );5859// Implementation60public:61BLARGG_DISABLE_NOTHROW6263private:64BOOST::uint64_t remain_;65};666768// Supports seeking in addition to Data_Reader operations69class File_Reader : public Data_Reader {70public:7172// Size of file73BOOST::uint64_t size() const { return size_; }7475// Current position in file76BOOST::uint64_t tell() const { return size_ - remain(); }7778// Goes to new position79blargg_err_t seek( BOOST::uint64_t );8081// Derived interface82protected:83// Sets size and resets position84void set_size( BOOST::uint64_t n ) { size_ = n; Data_Reader::set_remain( n ); }85void set_size( int n ) { set_size( STATIC_CAST(BOOST::uint64_t, n) ); }86void set_size( long n ) { set_size( STATIC_CAST(BOOST::uint64_t, n) ); }8788// Sets reported position89void set_tell( BOOST::uint64_t i ) { assert( 0 <= i && i <= size_ ); Data_Reader::set_remain( size_ - i ); }9091// Do same as seek(). Guaranteed that 0 <= n <= size(). Value of tell() is updated92// AFTER this call succeeds, not before. set_* functions should NOT be called from this.93virtual blargg_err_t seek_v( BOOST::uint64_t n ) BLARGG_PURE( { (void)n; return blargg_ok; } )9495// Implementation96protected:97File_Reader() : size_( 0 ) { }9899virtual blargg_err_t skip_v( BOOST::uint64_t );100101private:102BOOST::uint64_t size_;103104void set_remain(); // avoid accidental use of set_remain105};106107108// Reads from file on disk109class Std_File_Reader : public File_Reader {110public:111112// Opens file113blargg_err_t open( const char path [] );114115// Closes file if one was open116void close();117118// Switches to unbuffered mode. Useful if buffering is already being119// done at a higher level.120void make_unbuffered();121122// Implementation123public:124Std_File_Reader();125virtual ~Std_File_Reader();126127protected:128virtual blargg_err_t read_v( void*, int );129virtual blargg_err_t seek_v( BOOST::uint64_t );130131private:132void* file_;133};134135136// Treats range of memory as a file137class Mem_File_Reader : public File_Reader {138public:139140Mem_File_Reader( const void* begin, long size );141142// Implementation143protected:144virtual blargg_err_t read_v( void*, int );145virtual blargg_err_t seek_v( int );146147private:148const char* const begin;149};150151152// Allows only count bytes to be read from reader passed153class Subset_Reader : public Data_Reader {154public:155156Subset_Reader( Data_Reader*, BOOST::uint64_t count );157158// Implementation159protected:160virtual blargg_err_t read_v( void*, int );161162private:163Data_Reader* const in;164};165166167// Joins already-read header and remaining data into original file.168// Meant for cases where you've already read header and don't want169// to seek and re-read data (for efficiency).170class Remaining_Reader : public Data_Reader {171public:172173Remaining_Reader( void const* header, int header_size, Data_Reader* );174175// Implementation176protected:177virtual blargg_err_t read_v( void*, int );178179private:180Data_Reader* const in;181void const* header;182int header_remain;183};184185186// Invokes callback function to read data187extern "C" { // necessary to be usable from C188typedef const char* (*callback_reader_func_t)(189void* user_data, // Same value passed to constructor190void* out, // Buffer to place data into191int count // Number of bytes to read192);193}194class Callback_Reader : public Data_Reader {195public:196typedef callback_reader_func_t callback_t;197Callback_Reader( callback_t, BOOST::uint64_t size, void* user_data );198199// Implementation200protected:201virtual blargg_err_t read_v( void*, int );202203private:204callback_t const callback;205void* const user_data;206};207208209// Invokes callback function to read data210extern "C" { // necessary to be usable from C211typedef const char* (*callback_file_reader_func_t)(212void* user_data, // Same value passed to constructor213void* out, // Buffer to place data into214int count, // Number of bytes to read215BOOST::uint64_t pos // Position in file to read from216);217}218class Callback_File_Reader : public File_Reader {219public:220typedef callback_file_reader_func_t callback_t;221Callback_File_Reader( callback_t, BOOST::uint64_t size, void* user_data );222223// Implementation224protected:225virtual blargg_err_t read_v( void*, int );226virtual blargg_err_t seek_v( int );227228private:229callback_t const callback;230void* const user_data;231};232233234#ifdef HAVE_ZLIB_H235236// Reads file compressed with gzip (or uncompressed)237class Gzip_File_Reader : public File_Reader {238public:239240// Opens possibly gzipped file241blargg_err_t open( const char path [] );242243// Closes file if one was open244void close();245246// Implementation247public:248Gzip_File_Reader();249~Gzip_File_Reader();250251protected:252virtual blargg_err_t read_v( void*, int );253virtual blargg_err_t seek_v( int );254255private:256// void* so "zlib.h" doesn't have to be included here257void* file_;258};259#endif260261char* blargg_to_utf8( const blargg_wchar_t* );262blargg_wchar_t* blargg_to_wide( const char* );263264#endif265266267