#include #include #include #include #include #include using namespace std; #include "fetch.h" class libfetch_buffer : public streambuf { public: explicit libfetch_buffer( fetchIO *io, size_t bufSize = 256, size_t putBack = 1 ); private: int_type underflow( ); private: fetchIO *m_io; const size_t m_putBack; vector m_buf; }; libfetch_buffer::libfetch_buffer( fetchIO *io, size_t bufSize, size_t putBack ) : m_io( io ), m_putBack( max( putBack, size_t( 1 ) ) ), m_buf( max( bufSize, putBack ) + putBack ) { char *end = &m_buf.front( ) + m_buf.size( ); setg( end, end, end ); } streambuf::int_type libfetch_buffer::underflow( ) { // check if buffer is exhausted, if not, return current character if( gptr( ) < egptr( ) ) return traits_type::to_int_type( *gptr( ) ); char *base = &m_buf.front( ); char *start = base; // move put back away if( eback( ) == base ) { memmove( base, egptr( ) - m_putBack, m_putBack ); start += m_putBack; } // read from source ssize_t n = fetchIO_read( m_io, start, m_buf.size( ) - ( start - base ) ); if( n == 0 ) { return traits_type::eof( ); } else if( n < 0 ) { // TODO handle error } // set pointers setg( base, start, start + n ); return traits_type::to_int_type( *gptr( ) ); } class libfetch_istream : public istream { public: libfetch_istream( const char *url ); ~libfetch_istream( ); string lastErrMsg( ) const; private: fetchIO *m_io; libfetch_buffer *m_buf; }; libfetch_istream::libfetch_istream( const char *url ) : m_io( 0 ), m_buf( 0 ) { m_io = fetchGetURL( url, "" ); if( m_io == NULL ) { setstate( badbit ); return; } m_buf = new libfetch_buffer( m_io ); rdbuf( m_buf ); } libfetch_istream::~libfetch_istream( ) { if( m_buf ) delete m_buf; if( m_io ) fetchIO_close( m_io ); } string libfetch_istream::lastErrMsg( ) const { return fetchLastErrString; } int main( int argc, char *argv[] ) { char *urlstring; if( argc != 2 ) { cerr << "Usage: test2 " << endl; return 1; } urlstring = argv[1]; fetchTimeout = 2; libfetch_istream is( urlstring ); string s; if( !is.good( ) ) { cerr << "ERROR in libfetch input stream: " << is.lastErrMsg( ) << endl; return 1; } while( is.good( ) && !is.eof( ) ) { getline( is, s ); cout << s << endl; } return 0; }