[162] | 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 // |
---|