From ed704ce2e0ec5ebb64a07c68f977a830a8e7d161 Mon Sep 17 00:00:00 2001 From: graehl Date: Thu, 24 Jun 2010 22:35:36 +0000 Subject: robustness: throw exception on gzstream error git-svn-id: https://ws10smt.googlecode.com/svn/trunk@22 ec762483-ff6d-05da-a07a-a48fb63a330f --- decoder/gzstream.cc | 25 ++++++++++++++++++++----- decoder/gzstream.h | 24 +++++++++++++++--------- 2 files changed, 35 insertions(+), 14 deletions(-) diff --git a/decoder/gzstream.cc b/decoder/gzstream.cc index 9703e6ad..aa015bff 100644 --- a/decoder/gzstream.cc +++ b/decoder/gzstream.cc @@ -21,14 +21,15 @@ // Revision : $Revision: 1.1 $ // Revision_date : $Date: 2006/03/30 04:05:52 $ // Author(s) : Deepak Bandyopadhyay, Lutz Kettner -// -// Standard streambuf implementation following Nicolai Josuttis, "The +// +// Standard streambuf implementation following Nicolai Josuttis, "The // Standard C++ Library". // ============================================================================ #include "gzstream.h" #include #include +#include #ifdef GZSTREAM_NAMESPACE namespace GZSTREAM_NAMESPACE { @@ -59,6 +60,7 @@ gzstreambuf* gzstreambuf::open( const char* name, int open_mode) { *fmodeptr++ = 'b'; *fmodeptr = '\0'; file = gzopen( name, fmode); + if (!file) handle_gzerror(); if (file == 0) return (gzstreambuf*)0; opened = 1; @@ -71,10 +73,19 @@ gzstreambuf * gzstreambuf::close() { opened = 0; if ( gzclose( file) == Z_OK) return this; + else + handle_gzerror(); } return (gzstreambuf*)0; } +void gzstreambuf::handle_gzerror() { + int errnum; + const char *errmsg=gzerror(file,&errnum); + if (errnum==Z_DATA_ERROR) errmsg="CRC error reading gzip"; + throw std::runtime_error(std::string("gzstreambuf error: ")+errmsg); +} + int gzstreambuf::underflow() { // used for input buffer only if ( gptr() && ( gptr() < egptr())) return * reinterpret_cast( gptr()); @@ -89,7 +100,11 @@ int gzstreambuf::underflow() { // used for input buffer only int num = gzread( file, buffer+4, bufferSize-4); if (num <= 0) // ERROR or EOF - return EOF; + { + if (gzeof(file)) + return EOF; + handle_gzerror(); + } // reset buffer pointers setg( buffer + (4 - n_putback), // beginning of putback area @@ -97,7 +112,7 @@ int gzstreambuf::underflow() { // used for input buffer only buffer + 4 + num); // end of buffer // return next character - return * reinterpret_cast( gptr()); + return * reinterpret_cast( gptr()); } int gzstreambuf::flush_buffer() { @@ -105,7 +120,7 @@ int gzstreambuf::flush_buffer() { // sync() operation. int w = pptr() - pbase(); if ( gzwrite( file, pbase(), w) != w) - return EOF; + handle_gzerror(); pbump( -w); return w; } diff --git a/decoder/gzstream.h b/decoder/gzstream.h index ad9785fd..5c709490 100644 --- a/decoder/gzstream.h +++ b/decoder/gzstream.h @@ -21,8 +21,8 @@ // Revision : $Revision: 1.1 $ // Revision_date : $Date: 2006/03/30 04:05:52 $ // Author(s) : Deepak Bandyopadhyay, Lutz Kettner -// -// Standard streambuf implementation following Nicolai Josuttis, "The +// +// Standard streambuf implementation following Nicolai Josuttis, "The // Standard C++ Library". // ============================================================================ @@ -44,7 +44,7 @@ namespace GZSTREAM_NAMESPACE { class gzstreambuf : public std::streambuf { private: - static const int bufferSize = 47+256; // size of data buff + static const int bufferSize = 47+(1024*256); // size of data buff // totals 512 bytes under g++ for igzstream at the end. gzFile file; // file handle for compressed file @@ -53,19 +53,25 @@ private: int mode; // I/O mode int flush_buffer(); + void handle_gzerror(); // throws exception public: +#if defined(_WIN32) && !defined(CYGWIN) && !defined(EOF) + enum { + EOF = -1 + }; +#endif gzstreambuf() : opened(0) { setp( buffer, buffer + (bufferSize-1)); setg( buffer + 4, // beginning of putback area buffer + 4, // read position - buffer + 4); // end position + buffer + 4); // end position // ASSERT: both input & output capabilities will not be used together } int is_open() { return opened; } gzstreambuf* open( const char* name, int open_mode); gzstreambuf* close(); ~gzstreambuf() { close(); } - + virtual int overflow( int c = EOF); virtual int underflow(); virtual int sync(); @@ -85,15 +91,15 @@ public: // ---------------------------------------------------------------------------- // User classes. Use igzstream and ogzstream analogously to ifstream and -// ofstream respectively. They read and write files based on the gz* +// ofstream respectively. They read and write files based on the gz* // function interface of the zlib. Files are compatible with gzip compression. // ---------------------------------------------------------------------------- class igzstream : public gzstreambase, public std::istream { public: - igzstream() : std::istream( &buf) {} + igzstream() : std::istream( &buf) {} igzstream( const char* name, int open_mode = std::ios::in) - : gzstreambase( name, open_mode), std::istream( &buf) {} + : gzstreambase( name, std::ios::in | open_mode), std::istream( &buf) {} gzstreambuf* rdbuf() { return gzstreambase::rdbuf(); } void open( const char* name, int open_mode = std::ios::in) { gzstreambase::open( name, open_mode); @@ -104,7 +110,7 @@ class ogzstream : public gzstreambase, public std::ostream { public: ogzstream() : std::ostream( &buf) {} ogzstream( const char* name, int mode = std::ios::out) - : gzstreambase( name, mode), std::ostream( &buf) {} + : gzstreambase( name, mode), std::ostream( &buf) {} gzstreambuf* rdbuf() { return gzstreambase::rdbuf(); } void open( const char* name, int open_mode = std::ios::out) { gzstreambase::open( name, open_mode); -- cgit v1.2.3