[3107] | 1 | // ============================================================================
|
---|
| 2 | // gzstream, C++ iostream classes wrapping the zlib compression library.
|
---|
| 3 | // Copyright (C) 2001 Deepak Bandyopadhyay, Lutz Kettner
|
---|
| 4 | //
|
---|
| 5 | // This library is free software; you can redistribute it and/or
|
---|
| 6 | // modify it under the terms of the GNU Lesser General Public
|
---|
| 7 | // License as published by the Free Software Foundation; either
|
---|
| 8 | // version 2.1 of the License, or (at your option) any later version.
|
---|
| 9 | //
|
---|
| 10 | // This library is distributed in the hope that it will be useful,
|
---|
| 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
|
---|
| 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
---|
| 13 | // Lesser General Public License for more details.
|
---|
| 14 | //
|
---|
| 15 | // You should have received a copy of the GNU Lesser General Public
|
---|
| 16 | // License along with this library; if not, write to the Free Software
|
---|
| 17 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
---|
| 18 | // ============================================================================
|
---|
| 19 | //
|
---|
| 20 | // File : gzstream.C
|
---|
| 21 | // Revision : $Revision: 1.1 $
|
---|
| 22 | // Revision_date : $Date: 2004/02/16 14:46:00 $
|
---|
| 23 | // Author(s) : Deepak Bandyopadhyay, Lutz Kettner
|
---|
| 24 | //
|
---|
| 25 | // Standard streambuf implementation following Nicolai Josuttis, "The
|
---|
| 26 | // Standard C++ Library".
|
---|
| 27 | // ============================================================================
|
---|
| 28 |
|
---|
| 29 | #include "gzstream.h"
|
---|
| 30 | #include <string.h> // for memcpy
|
---|
| 31 |
|
---|
| 32 | #ifdef GZSTREAM_NAMESPACE
|
---|
| 33 | namespace GZSTREAM_NAMESPACE {
|
---|
| 34 | #endif
|
---|
| 35 |
|
---|
| 36 | // ----------------------------------------------------------------------------
|
---|
| 37 | // Internal classes to implement gzstream. See header file for user classes.
|
---|
| 38 | // ----------------------------------------------------------------------------
|
---|
| 39 |
|
---|
| 40 | // --------------------------------------
|
---|
| 41 | // class gzstreambuf:
|
---|
| 42 | // --------------------------------------
|
---|
| 43 |
|
---|
| 44 | gzstreambuf*
|
---|
| 45 | gzstreambuf::open( const char* name, int open_mode) {
|
---|
| 46 | if ( is_open() )
|
---|
| 47 | return (gzstreambuf*)0;
|
---|
| 48 | mode = open_mode;
|
---|
| 49 | // no append nor read/write mode
|
---|
| 50 | if ((mode & std::ios::ate) || (mode & std::ios::app)
|
---|
| 51 | || ((mode & std::ios::in) && (mode & std::ios::out)))
|
---|
| 52 | return (gzstreambuf*)0;
|
---|
| 53 | char fmode[10];
|
---|
| 54 | char* fmodeptr = fmode;
|
---|
| 55 | if ( mode & std::ios::in)
|
---|
| 56 | *fmodeptr++ = 'r';
|
---|
| 57 | else
|
---|
| 58 | if ( mode & std::ios::out)
|
---|
| 59 | *fmodeptr++ = 'w';
|
---|
| 60 | *fmodeptr++ = 'b';
|
---|
| 61 | *fmodeptr = '\0';
|
---|
| 62 | file = gzopen( name, fmode);
|
---|
| 63 | if (file == 0)
|
---|
| 64 | return (gzstreambuf*)0;
|
---|
| 65 | opened = 1;
|
---|
| 66 | return this;
|
---|
| 67 | }
|
---|
| 68 |
|
---|
| 69 | gzstreambuf *
|
---|
| 70 | gzstreambuf::close() {
|
---|
| 71 | if ( is_open()) {
|
---|
| 72 | sync();
|
---|
| 73 | opened = 0;
|
---|
| 74 | if ( gzclose( file) == Z_OK)
|
---|
| 75 | return this;
|
---|
| 76 | }
|
---|
| 77 | return (gzstreambuf*)0;
|
---|
| 78 | }
|
---|
| 79 |
|
---|
| 80 | int
|
---|
| 81 | gzstreambuf::underflow() { // used for input buffer only
|
---|
| 82 | if ( gptr() && ( gptr() < egptr()))
|
---|
| 83 | return * reinterpret_cast<unsigned char *>( gptr());
|
---|
| 84 |
|
---|
| 85 | if ( ! (mode & std::ios::in) || ! opened)
|
---|
| 86 | return EOF;
|
---|
| 87 | // Josuttis' implementation of inbuf
|
---|
| 88 | int n_putback = gptr() - eback();
|
---|
| 89 | if ( n_putback > 4)
|
---|
| 90 | n_putback = 4;
|
---|
| 91 | memcpy( buffer + (4 - n_putback), gptr() - n_putback, n_putback);
|
---|
| 92 |
|
---|
| 93 | int num = gzread( file, buffer+4, gzbufferSize-4);
|
---|
| 94 | if (num <= 0) // ERROR or EOF
|
---|
| 95 | return EOF;
|
---|
| 96 |
|
---|
| 97 | // reset buffer pointers
|
---|
| 98 | setg( buffer + (4 - n_putback), // beginning of putback area
|
---|
| 99 | buffer + 4, // read position
|
---|
| 100 | buffer + 4 + num); // end of buffer
|
---|
| 101 |
|
---|
| 102 | // return next character
|
---|
| 103 | return * reinterpret_cast<unsigned char *>( gptr());
|
---|
| 104 | }
|
---|
| 105 |
|
---|
| 106 | int
|
---|
| 107 | gzstreambuf::flush_buffer() {
|
---|
| 108 | // Separate the writing of the buffer from overflow() and
|
---|
| 109 | // sync() operation.
|
---|
| 110 | int w = pptr() - pbase();
|
---|
| 111 | if ( gzwrite( file, pbase(), w) != w)
|
---|
| 112 | return EOF;
|
---|
| 113 | pbump( -w);
|
---|
| 114 | return w;
|
---|
| 115 | }
|
---|
| 116 |
|
---|
| 117 | int
|
---|
| 118 | gzstreambuf::overflow( int c) { // used for output buffer only
|
---|
| 119 | if ( ! ( mode & std::ios::out) || ! opened)
|
---|
| 120 | return EOF;
|
---|
| 121 | if (c != EOF) {
|
---|
| 122 | *pptr() = c;
|
---|
| 123 | pbump(1);
|
---|
| 124 | }
|
---|
| 125 | if ( flush_buffer() == EOF)
|
---|
| 126 | return EOF;
|
---|
| 127 | return c;
|
---|
| 128 | }
|
---|
| 129 |
|
---|
| 130 | int
|
---|
| 131 | gzstreambuf::sync() {
|
---|
| 132 | // Changed to use flush_buffer() instead of overflow( EOF)
|
---|
| 133 | // which caused improper behavior with std::endl and flush(),
|
---|
| 134 | // bug reported by Vincent Ricard.
|
---|
| 135 | if ( pptr() && pptr() > pbase()) {
|
---|
| 136 | if ( flush_buffer() == EOF)
|
---|
| 137 | return -1;
|
---|
| 138 | }
|
---|
| 139 | return 0;
|
---|
| 140 | }
|
---|
| 141 |
|
---|
| 142 |
|
---|
| 143 | // --------------------------------------
|
---|
| 144 | // class gzstreambase:
|
---|
| 145 | // --------------------------------------
|
---|
| 146 |
|
---|
| 147 | gzstreambase::gzstreambase( const char* name, int mode)
|
---|
| 148 | {
|
---|
| 149 | init( &buf);
|
---|
| 150 | open( name, mode);
|
---|
| 151 | }
|
---|
| 152 |
|
---|
| 153 | gzstreambase::~gzstreambase()
|
---|
| 154 | {
|
---|
| 155 | buf.close();
|
---|
| 156 | }
|
---|
| 157 |
|
---|
| 158 | void
|
---|
| 159 | gzstreambase::open( const char* name, int open_mode) {
|
---|
| 160 | if ( ! buf.open( name, open_mode))
|
---|
| 161 | clear( rdstate() | std::ios::badbit);
|
---|
| 162 | }
|
---|
| 163 |
|
---|
| 164 | void gzstreambase::close() {
|
---|
| 165 | if ( buf.is_open())
|
---|
| 166 | if ( ! buf.close())
|
---|
| 167 | clear( rdstate() | std::ios::badbit);
|
---|
| 168 | }
|
---|
| 169 |
|
---|
| 170 | #ifdef GZSTREAM_NAMESPACE
|
---|
| 171 | } // namespace GZSTREAM_NAMESPACE
|
---|
| 172 | #endif
|
---|
| 173 |
|
---|
| 174 | // ============================================================================
|
---|
| 175 | // EOF //
|
---|